ESPHome 2026.6.0-dev
Loading...
Searching...
No Matches
ir_rf_proxy.cpp
Go to the documentation of this file.
1#include "ir_rf_proxy.h"
2
3#include <cinttypes>
4
5#include "esphome/core/log.h"
6
8
9static const char *const TAG = "ir_rf_proxy";
10
11// ========== Shared transmit helper ==========
12// Static template: all instantiations occur in this translation unit.
13
14template<typename CallT>
15static void transmit_raw_timings(remote_base::RemoteTransmitterBase *transmitter, uint32_t carrier_frequency,
16 const CallT &call) {
17 if (transmitter == nullptr) {
18 ESP_LOGW(TAG, "No transmitter configured");
19 return;
20 }
21
22 if (!call.has_raw_timings()) {
23 ESP_LOGE(TAG, "No raw timings provided");
24 return;
25 }
26
27 auto transmit_call = transmitter->transmit();
28 auto *transmit_data = transmit_call.get_data();
29 transmit_data->set_carrier_frequency(carrier_frequency);
30
31 if (call.is_packed()) {
32 transmit_data->set_data_from_packed_sint32(call.get_packed_data(), call.get_packed_length(),
33 call.get_packed_count());
34 ESP_LOGD(TAG, "Transmitting packed raw timings: count=%" PRIu16 ", repeat=%" PRIu32, call.get_packed_count(),
35 call.get_repeat_count());
36 } else if (call.is_base64url()) {
37 if (!transmit_data->set_data_from_base64url(call.get_base64url_data())) {
38 ESP_LOGE(TAG, "Invalid base64url data");
39 return;
40 }
41 constexpr int32_t max_timing_us = 500000;
42 for (int32_t timing : transmit_data->get_data()) {
43 int32_t abs_timing = timing < 0 ? -timing : timing;
44 if (abs_timing > max_timing_us) {
45 ESP_LOGE(TAG, "Invalid timing value: %" PRId32 " µs (max %" PRId32 ")", timing, max_timing_us);
46 return;
47 }
48 }
49 ESP_LOGD(TAG, "Transmitting base64url raw timings: count=%zu, repeat=%" PRIu32, transmit_data->get_data().size(),
50 call.get_repeat_count());
51 } else {
52 transmit_data->set_data(call.get_raw_timings());
53 ESP_LOGD(TAG, "Transmitting raw timings: count=%zu, repeat=%" PRIu32, call.get_raw_timings().size(),
54 call.get_repeat_count());
55 }
56
57 if (call.get_repeat_count() > 0) {
58 transmit_call.set_send_times(call.get_repeat_count());
59 }
60
61 transmit_call.perform();
62}
63
64// ========== IrRfProxy (Infrared platform) ==========
65
66#ifdef USE_IR_RF
67
69 ESP_LOGCONFIG(TAG,
70 "IR Proxy '%s'\n"
71 " Supports Transmitter: %s\n"
72 " Supports Receiver: %s",
73 this->get_name().c_str(), YESNO(this->traits_.get_supports_transmitter()),
74 YESNO(this->traits_.get_supports_receiver()));
75
76 if (this->is_rf()) {
77 ESP_LOGCONFIG(TAG, " Hardware Type: RF (%.3f MHz)", this->frequency_khz_ / 1e3f);
78 } else {
79 ESP_LOGCONFIG(TAG, " Hardware Type: Infrared");
80 }
81}
82
84 uint32_t carrier = call.get_carrier_frequency().value_or(0);
85 transmit_raw_timings(this->transmitter_, carrier, call);
86}
87
88#endif // USE_IR_RF
89
90// ========== RfProxy (Radio Frequency platform) ==========
91
92#ifdef USE_RADIO_FREQUENCY
93
95 this->traits_.set_supports_transmitter(this->transmitter_ != nullptr);
96 this->traits_.set_supports_receiver(this->receiver_ != nullptr);
97
98 // remote_transmitter/receiver always uses OOK (on-off keying)
100
101 if (this->receiver_ != nullptr) {
102 this->receiver_->register_listener(this);
103 }
104}
105
107 ESP_LOGCONFIG(TAG,
108 "RF Proxy '%s'\n"
109 " Supports Transmitter: %s\n"
110 " Supports Receiver: %s",
111 this->get_name().c_str(), YESNO(this->traits_.get_supports_transmitter()),
112 YESNO(this->traits_.get_supports_receiver()));
113
114 const auto &traits = this->traits_;
115 if (traits.get_frequency_min_hz() > 0) {
116 if (traits.get_frequency_min_hz() == traits.get_frequency_max_hz()) {
117 ESP_LOGCONFIG(TAG, " Frequency: %.3f MHz (fixed)", traits.get_frequency_min_hz() / 1e6f);
118 } else {
119 ESP_LOGCONFIG(TAG, " Frequency Range: %.3f - %.3f MHz", traits.get_frequency_min_hz() / 1e6f,
120 traits.get_frequency_max_hz() / 1e6f);
121 }
122 }
123}
124
126 // RF: no IR carrier modulation. Any RF front-end coordination (state turnaround, retuning)
127 // happens via the radio_frequency entity's on_control trigger and remote_transmitter's
128 // on_transmit/on_complete triggers — wired up in user YAML.
129 transmit_raw_timings(this->transmitter_, 0, call);
130}
131
132#endif // USE_RADIO_FREQUENCY
133
134} // namespace esphome::ir_rf_proxy
const StringRef & get_name() const
Definition entity_base.h:71
InfraredCall - Builder pattern for transmitting infrared signals.
Definition infrared.h:25
remote_base::RemoteTransmitterBase * transmitter_
Definition infrared.h:153
bool get_supports_transmitter() const
Definition infrared.h:98
void control(const infrared::InfraredCall &call) override
bool is_rf() const
Check if this is RF mode (non-zero frequency)
Definition ir_rf_proxy.h:32
remote_base::RemoteTransmitterBase * transmitter_
Definition ir_rf_proxy.h:68
void control(const radio_frequency::RadioFrequencyCall &call) override
remote_base::RemoteReceiverBase * receiver_
Definition ir_rf_proxy.h:69
RadioFrequencyCall - Builder pattern for transmitting radio frequency signals.
void add_supported_modulation(RadioFrequencyModulation mod)
void register_listener(RemoteReceiverListener *listener)
void set_carrier_frequency(uint32_t carrier_frequency)
Definition remote_base.h:29
static void uint32_t