ESPHome 2026.5.0-dev
Loading...
Searching...
No Matches
infrared.cpp
Go to the documentation of this file.
1#include "infrared.h"
2
3#include <cinttypes>
4
5#include "esphome/core/log.h"
6
7#ifdef USE_API
9#endif
10
12
13static const char *const TAG = "infrared";
14
15// ========== InfraredCall ==========
16
21
22InfraredCall &InfraredCall::set_raw_timings(const std::vector<int32_t> &timings) {
23 this->raw_timings_ = &timings;
24 this->packed_data_ = nullptr;
25 this->base64url_ptr_ = nullptr;
26 return *this;
27}
28
30 this->base64url_ptr_ = &base64url;
31 this->raw_timings_ = nullptr;
32 this->packed_data_ = nullptr;
33 return *this;
34}
35
36InfraredCall &InfraredCall::set_raw_timings_packed(const uint8_t *data, uint16_t length, uint16_t count) {
37 this->packed_data_ = data;
38 this->packed_length_ = length;
39 this->packed_count_ = count;
40 this->raw_timings_ = nullptr;
41 this->base64url_ptr_ = nullptr;
42 return *this;
43}
44
46 this->repeat_count_ = count;
47 return *this;
48}
49
51 if (this->parent_ != nullptr) {
52 this->parent_->control(*this);
53 }
54}
55
56// ========== Infrared ==========
57
59 // Set up traits based on configuration
62
63 // Register as listener for received IR data
64 if (this->receiver_ != nullptr) {
65 this->receiver_->register_listener(this);
66 }
67}
68
70 ESP_LOGCONFIG(TAG,
71 "Infrared '%s'\n"
72 " Supports Transmitter: %s\n"
73 " Supports Receiver: %s",
74 this->get_name().c_str(), YESNO(this->traits_.get_supports_transmitter()),
75 YESNO(this->traits_.get_supports_receiver()));
76}
77
79
81 if (this->transmitter_ == nullptr) {
82 ESP_LOGW(TAG, "No transmitter configured");
83 return;
84 }
85
86 if (!call.has_raw_timings()) {
87 ESP_LOGE(TAG, "No raw timings provided");
88 return;
89 }
90
91 // Create transmit data object
92 auto transmit_call = this->transmitter_->transmit();
93 auto *transmit_data = transmit_call.get_data();
94
95 // Set carrier frequency
96 auto freq = call.get_carrier_frequency();
97 if (freq.has_value()) {
98 transmit_data->set_carrier_frequency(*freq);
99 }
100
101 // Set timings based on format
102 if (call.is_packed()) {
103 // Zero-copy from packed protobuf data
104 transmit_data->set_data_from_packed_sint32(call.get_packed_data(), call.get_packed_length(),
105 call.get_packed_count());
106 ESP_LOGD(TAG, "Transmitting packed raw timings: count=%" PRIu16 ", repeat=%" PRIu32, call.get_packed_count(),
107 call.get_repeat_count());
108 } else if (call.is_base64url()) {
109 // Decode base64url (URL-safe) into transmit buffer
110 if (!transmit_data->set_data_from_base64url(call.get_base64url_data())) {
111 ESP_LOGE(TAG, "Invalid base64url data");
112 return;
113 }
114 // Sanity check: validate timing values are within reasonable bounds
115 constexpr int32_t max_timing_us = 500000; // 500ms absolute max
116 for (int32_t timing : transmit_data->get_data()) {
117 int32_t abs_timing = timing < 0 ? -timing : timing;
118 if (abs_timing > max_timing_us) {
119 ESP_LOGE(TAG, "Invalid timing value: %" PRId32 " µs (max %" PRId32 ")", timing, max_timing_us);
120 return;
121 }
122 }
123 ESP_LOGD(TAG, "Transmitting base64url raw timings: count=%zu, repeat=%" PRIu32, transmit_data->get_data().size(),
124 call.get_repeat_count());
125 } else {
126 // From vector (lambdas/automations)
127 transmit_data->set_data(call.get_raw_timings());
128 ESP_LOGD(TAG, "Transmitting raw timings: count=%zu, repeat=%" PRIu32, call.get_raw_timings().size(),
129 call.get_repeat_count());
130 }
131
132 // Set repeat count
133 if (call.get_repeat_count() > 0) {
134 transmit_call.set_send_times(call.get_repeat_count());
135 }
136
137 // Perform transmission
138 transmit_call.perform();
139}
140
142 uint32_t flags = 0;
143
144 // Add transmit/receive capability based on traits
147 if (this->traits_.get_supports_receiver())
149
150 return flags;
151}
152
154 // Forward received IR data to API server
155#if defined(USE_API) && defined(USE_IR_RF)
156 if (api::global_api_server != nullptr) {
157#ifdef USE_DEVICES
158 uint32_t device_id = this->get_device_id();
159#else
160 uint32_t device_id = 0;
161#endif
163 }
164#endif
165 return false; // Don't consume the event, allow other listeners to process it
166}
167
168} // namespace esphome::infrared
uint16_le_t frequency
Definition bl0942.h:6
const StringRef & get_name() const
Definition entity_base.h:71
ESPDEPRECATED("Use get_icon_to() instead. Will be removed in ESPHome 2026.9.0", "2026.3.0") std uint32_t get_device_id() const
ESPDEPRECATED("object_id mangles names and all object_id methods are planned for removal " "(see https://github.com/esphome/backlog/issues/76). " "Now is the time to stop using object_id. If still needed, use get_object_id_to() " "which will remain available longer. get_object_id() will be removed in 2026.7.0", "2025.12.0") std uint32_t get_object_id_hash() const
Definition entity_base.h:89
void send_infrared_rf_receive_event(uint32_t device_id, uint32_t key, const std::vector< int32_t > *timings)
InfraredCall - Builder pattern for transmitting infrared signals.
Definition infrared.h:25
InfraredCall & set_raw_timings(const std::vector< int32_t > &timings)
Set the raw timings from a vector (positive = mark, negative = space)
Definition infrared.cpp:22
InfraredCall & set_carrier_frequency(uint32_t frequency)
Set the carrier frequency in Hz.
Definition infrared.cpp:17
InfraredCall & set_repeat_count(uint32_t count)
Set the number of times to repeat transmission (1 = transmit once, 2 = transmit twice,...
Definition infrared.cpp:45
void perform()
Perform the transmission.
Definition infrared.cpp:50
InfraredCall & set_raw_timings_packed(const uint8_t *data, uint16_t length, uint16_t count)
Set the raw timings from packed protobuf sint32 data (zigzag + varint encoded)
Definition infrared.cpp:36
const std::string * base64url_ptr_
Definition infrared.h:88
optional< uint32_t > carrier_frequency_
Definition infrared.h:84
const uint8_t * packed_data_
Definition infrared.h:90
InfraredCall & set_raw_timings_base64url(const std::string &base64url)
Set the raw timings from base64url-encoded little-endian int32 data.
Definition infrared.cpp:29
const std::vector< int32_t > * raw_timings_
Definition infrared.h:86
void dump_config() override
Definition infrared.cpp:69
remote_base::RemoteReceiverBase * receiver_
Definition infrared.h:152
bool on_receive(remote_base::RemoteReceiveData data) override
Called when IR data is received (from RemoteReceiverListener)
Definition infrared.cpp:153
InfraredCall make_call()
Create a call object for transmitting.
Definition infrared.cpp:78
virtual void control(const InfraredCall &call)
Perform the actual transmission (called by InfraredCall)
Definition infrared.cpp:80
remote_base::RemoteTransmitterBase * transmitter_
Definition infrared.h:153
bool has_transmitter() const
Check if this infrared has a transmitter configured.
Definition infrared.h:128
bool has_receiver() const
Check if this infrared has a receiver configured.
Definition infrared.h:130
uint32_t get_capability_flags() const
Get capability flags for this infrared instance.
Definition infrared.cpp:141
bool get_supports_transmitter() const
Definition infrared.h:98
void set_supports_transmitter(bool supports)
Definition infrared.h:99
void set_supports_receiver(bool supports)
Definition infrared.h:102
const RawTimings & get_raw_data() const
Definition remote_base.h:59
void register_listener(RemoteReceiverListener *listener)
uint16_t flags
APIServer * global_api_server
static void uint32_t
uint16_t length
Definition tt21100.cpp:0