diff --git a/esphome/components/infrared/infrared.cpp b/esphome/components/infrared/infrared.cpp index 5a909738c6..83039a5a9b 100644 --- a/esphome/components/infrared/infrared.cpp +++ b/esphome/components/infrared/infrared.cpp @@ -59,11 +59,6 @@ void Infrared::setup() { // Set up traits based on configuration this->traits_.set_supports_transmitter(this->has_transmitter()); this->traits_.set_supports_receiver(this->has_receiver()); - - // Register as listener for received IR data - if (this->receiver_ != nullptr) { - this->receiver_->register_listener(this); - } } void Infrared::dump_config() { diff --git a/esphome/components/ir_rf_proxy/infrared.py b/esphome/components/ir_rf_proxy/infrared.py index 3218889721..54e53f52d4 100644 --- a/esphome/components/ir_rf_proxy/infrared.py +++ b/esphome/components/ir_rf_proxy/infrared.py @@ -3,7 +3,12 @@ from typing import Any import esphome.codegen as cg -from esphome.components import infrared, remote_receiver, remote_transmitter +from esphome.components import ( + infrared, + remote_base, + remote_receiver, + remote_transmitter, +) from esphome.components.const import CONF_RECEIVER_FREQUENCY import esphome.config_validation as cv from esphome.const import CONF_CARRIER_DUTY_PERCENT, CONF_FREQUENCY @@ -84,6 +89,7 @@ async def to_code(config: dict[str, Any]) -> None: if CONF_REMOTE_RECEIVER_ID in config: receiver = await cg.get_variable(config[CONF_REMOTE_RECEIVER_ID]) cg.add(var.set_receiver(receiver)) + remote_base.add_listener(receiver, var) # Set receiver demodulation frequency if specified (metadata only, no hardware effect) if CONF_RECEIVER_FREQUENCY in config: diff --git a/esphome/components/ir_rf_proxy/ir_rf_proxy.cpp b/esphome/components/ir_rf_proxy/ir_rf_proxy.cpp index c13c6198cb..ceb4c9a67c 100644 --- a/esphome/components/ir_rf_proxy/ir_rf_proxy.cpp +++ b/esphome/components/ir_rf_proxy/ir_rf_proxy.cpp @@ -97,10 +97,6 @@ void RfProxy::setup() { // remote_transmitter/receiver always uses OOK (on-off keying) this->traits_.add_supported_modulation(radio_frequency::RadioFrequencyModulation::RADIO_FREQUENCY_MODULATION_OOK); - - if (this->receiver_ != nullptr) { - this->receiver_->register_listener(this); - } } void RfProxy::dump_config() { diff --git a/esphome/components/ir_rf_proxy/radio_frequency.py b/esphome/components/ir_rf_proxy/radio_frequency.py index a243909837..a4971a30ee 100644 --- a/esphome/components/ir_rf_proxy/radio_frequency.py +++ b/esphome/components/ir_rf_proxy/radio_frequency.py @@ -1,7 +1,12 @@ """Radio Frequency platform implementation using remote_base (remote_transmitter/receiver).""" import esphome.codegen as cg -from esphome.components import radio_frequency, remote_receiver, remote_transmitter +from esphome.components import ( + radio_frequency, + remote_base, + remote_receiver, + remote_transmitter, +) import esphome.config_validation as cv from esphome.const import CONF_CARRIER_DUTY_PERCENT, CONF_FREQUENCY import esphome.final_validate as fv @@ -68,3 +73,4 @@ async def to_code(config: ConfigType) -> None: if CONF_REMOTE_RECEIVER_ID in config: receiver = await cg.get_variable(config[CONF_REMOTE_RECEIVER_ID]) cg.add(var.set_receiver(receiver)) + remote_base.add_listener(receiver, var) diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index 19b8549f75..140efb838c 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -40,7 +40,9 @@ from esphome.const import ( CONF_ZERO, ) from esphome.core import ID, coroutine +from esphome.cpp_generator import MockObj from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor +from esphome.types import ConfigType from esphome.util import Registry, SimpleRegistry AUTO_LOAD = ["binary_sensor"] @@ -90,9 +92,25 @@ REMOTE_TRANSMITTABLE_SCHEMA = cv.Schema( ) -async def register_listener(var, config): +# Listener and dumper lists are StaticVectors sized from these counts, so every +# registration must go through add_listener / add_dumper +_request_listener_slot = cg.slot_counter("REMOTE_BASE_LISTENER_COUNT") +_request_dumper_slot = cg.slot_counter("REMOTE_BASE_DUMPER_COUNT") + + +def add_listener(receiver: MockObj, listener: MockObj) -> None: + _request_listener_slot() + cg.add(receiver.register_listener(listener)) + + +def add_dumper(receiver: MockObj, dumper: MockObj) -> None: + _request_dumper_slot() + cg.add(receiver.register_dumper(dumper)) + + +async def register_listener(var: MockObj, config: ConfigType) -> None: receiver = await cg.get_variable(config[CONF_RECEIVER_ID]) - cg.add(receiver.register_listener(var)) + add_listener(receiver, var) async def register_transmittable(var, config): diff --git a/esphome/components/remote_base/abbwelcome_protocol.h b/esphome/components/remote_base/abbwelcome_protocol.h index 7ff32923be..a309c124ee 100644 --- a/esphome/components/remote_base/abbwelcome_protocol.h +++ b/esphome/components/remote_base/abbwelcome_protocol.h @@ -191,9 +191,9 @@ class ABBWelcomeData { class ABBWelcomeProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const ABBWelcomeData &src) override; - optional decode(RemoteReceiveData src) override; - void dump(const ABBWelcomeData &data) override; + void encode(RemoteTransmitData *dst, const ABBWelcomeData &src); + optional decode(RemoteReceiveData src); + void dump(const ABBWelcomeData &data); protected: void encode_byte_(RemoteTransmitData *dst, uint8_t data) const; diff --git a/esphome/components/remote_base/aeha_protocol.h b/esphome/components/remote_base/aeha_protocol.h index 3f4e98bd43..98a5501155 100644 --- a/esphome/components/remote_base/aeha_protocol.h +++ b/esphome/components/remote_base/aeha_protocol.h @@ -15,9 +15,9 @@ struct AEHAData { class AEHAProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const AEHAData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const AEHAData &data) override; + void encode(RemoteTransmitData *dst, const AEHAData &data); + optional decode(RemoteReceiveData src); + void dump(const AEHAData &data); private: std::string format_data_(const std::vector &data); diff --git a/esphome/components/remote_base/beo4_protocol.h b/esphome/components/remote_base/beo4_protocol.h index 30b99dbeb7..ed9d6aa671 100644 --- a/esphome/components/remote_base/beo4_protocol.h +++ b/esphome/components/remote_base/beo4_protocol.h @@ -16,9 +16,9 @@ struct Beo4Data { class Beo4Protocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const Beo4Data &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const Beo4Data &data) override; + void encode(RemoteTransmitData *dst, const Beo4Data &data); + optional decode(RemoteReceiveData src); + void dump(const Beo4Data &data); }; DECLARE_REMOTE_PROTOCOL(Beo4) diff --git a/esphome/components/remote_base/brennenstuhl_protocol.h b/esphome/components/remote_base/brennenstuhl_protocol.h index 1d5b621714..bfea463b7d 100644 --- a/esphome/components/remote_base/brennenstuhl_protocol.h +++ b/esphome/components/remote_base/brennenstuhl_protocol.h @@ -13,9 +13,9 @@ struct BrennenstuhlData { class BrennenstuhlProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const BrennenstuhlData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const BrennenstuhlData &data) override; + void encode(RemoteTransmitData *dst, const BrennenstuhlData &data); + optional decode(RemoteReceiveData src); + void dump(const BrennenstuhlData &data); }; DECLARE_REMOTE_PROTOCOL(Brennenstuhl) diff --git a/esphome/components/remote_base/byronsx_protocol.h b/esphome/components/remote_base/byronsx_protocol.h index 674fa99ea1..c71390c267 100644 --- a/esphome/components/remote_base/byronsx_protocol.h +++ b/esphome/components/remote_base/byronsx_protocol.h @@ -21,9 +21,9 @@ struct ByronSXData { class ByronSXProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const ByronSXData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const ByronSXData &data) override; + void encode(RemoteTransmitData *dst, const ByronSXData &data); + optional decode(RemoteReceiveData src); + void dump(const ByronSXData &data); }; DECLARE_REMOTE_PROTOCOL(ByronSX) diff --git a/esphome/components/remote_base/canalsat_protocol.h b/esphome/components/remote_base/canalsat_protocol.h index 5ba9115ea8..09bead18b3 100644 --- a/esphome/components/remote_base/canalsat_protocol.h +++ b/esphome/components/remote_base/canalsat_protocol.h @@ -19,9 +19,9 @@ struct CanalSatLDData : public CanalSatData {}; class CanalSatBaseProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const CanalSatData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const CanalSatData &data) override; + void encode(RemoteTransmitData *dst, const CanalSatData &data); + optional decode(RemoteReceiveData src); + void dump(const CanalSatData &data); protected: uint16_t frequency_; diff --git a/esphome/components/remote_base/coolix_protocol.h b/esphome/components/remote_base/coolix_protocol.h index d9441e8417..29a306ce29 100644 --- a/esphome/components/remote_base/coolix_protocol.h +++ b/esphome/components/remote_base/coolix_protocol.h @@ -21,9 +21,9 @@ struct CoolixData { class CoolixProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const CoolixData &data) override; - optional decode(RemoteReceiveData data) override; - void dump(const CoolixData &data) override; + void encode(RemoteTransmitData *dst, const CoolixData &data); + optional decode(RemoteReceiveData data); + void dump(const CoolixData &data); }; DECLARE_REMOTE_PROTOCOL(Coolix) diff --git a/esphome/components/remote_base/dish_protocol.h b/esphome/components/remote_base/dish_protocol.h index c89f4e78e1..f319b55f43 100644 --- a/esphome/components/remote_base/dish_protocol.h +++ b/esphome/components/remote_base/dish_protocol.h @@ -13,9 +13,9 @@ struct DishData { class DishProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const DishData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const DishData &data) override; + void encode(RemoteTransmitData *dst, const DishData &data); + optional decode(RemoteReceiveData src); + void dump(const DishData &data); }; DECLARE_REMOTE_PROTOCOL(Dish) diff --git a/esphome/components/remote_base/dooya_protocol.h b/esphome/components/remote_base/dooya_protocol.h index 148c7c17bc..954c3cf1d3 100644 --- a/esphome/components/remote_base/dooya_protocol.h +++ b/esphome/components/remote_base/dooya_protocol.h @@ -20,9 +20,9 @@ struct DooyaData { class DooyaProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const DooyaData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const DooyaData &data) override; + void encode(RemoteTransmitData *dst, const DooyaData &data); + optional decode(RemoteReceiveData src); + void dump(const DooyaData &data); }; DECLARE_REMOTE_PROTOCOL(Dooya) diff --git a/esphome/components/remote_base/drayton_protocol.h b/esphome/components/remote_base/drayton_protocol.h index 693a1bbe85..4e879f0f75 100644 --- a/esphome/components/remote_base/drayton_protocol.h +++ b/esphome/components/remote_base/drayton_protocol.h @@ -19,9 +19,9 @@ struct DraytonData { class DraytonProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const DraytonData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const DraytonData &data) override; + void encode(RemoteTransmitData *dst, const DraytonData &data); + optional decode(RemoteReceiveData src); + void dump(const DraytonData &data); }; DECLARE_REMOTE_PROTOCOL(Drayton) diff --git a/esphome/components/remote_base/dyson_protocol.h b/esphome/components/remote_base/dyson_protocol.h index 3473a489b2..663e50fb4b 100644 --- a/esphome/components/remote_base/dyson_protocol.h +++ b/esphome/components/remote_base/dyson_protocol.h @@ -21,9 +21,9 @@ struct DysonData { class DysonProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const DysonData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const DysonData &data) override; + void encode(RemoteTransmitData *dst, const DysonData &data); + optional decode(RemoteReceiveData src); + void dump(const DysonData &data); }; DECLARE_REMOTE_PROTOCOL(Dyson) diff --git a/esphome/components/remote_base/gobox_protocol.h b/esphome/components/remote_base/gobox_protocol.h index f6b278771e..0c8797af70 100644 --- a/esphome/components/remote_base/gobox_protocol.h +++ b/esphome/components/remote_base/gobox_protocol.h @@ -31,9 +31,9 @@ class GoboxProtocol : public RemoteProtocol { void dump_timings_(const RawTimings &timings) const; public: - void encode(RemoteTransmitData *dst, const GoboxData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const GoboxData &data) override; + void encode(RemoteTransmitData *dst, const GoboxData &data); + optional decode(RemoteReceiveData src); + void dump(const GoboxData &data); }; DECLARE_REMOTE_PROTOCOL(Gobox) diff --git a/esphome/components/remote_base/haier_protocol.h b/esphome/components/remote_base/haier_protocol.h index 9c45ba1a63..e1fd60411f 100644 --- a/esphome/components/remote_base/haier_protocol.h +++ b/esphome/components/remote_base/haier_protocol.h @@ -13,9 +13,9 @@ struct HaierData { class HaierProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const HaierData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const HaierData &data) override; + void encode(RemoteTransmitData *dst, const HaierData &data); + optional decode(RemoteReceiveData src); + void dump(const HaierData &data); protected: void encode_byte_(RemoteTransmitData *dst, uint8_t item); diff --git a/esphome/components/remote_base/jvc_protocol.h b/esphome/components/remote_base/jvc_protocol.h index f6e2548dea..5911664fc3 100644 --- a/esphome/components/remote_base/jvc_protocol.h +++ b/esphome/components/remote_base/jvc_protocol.h @@ -14,9 +14,9 @@ struct JVCData { class JVCProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const JVCData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const JVCData &data) override; + void encode(RemoteTransmitData *dst, const JVCData &data); + optional decode(RemoteReceiveData src); + void dump(const JVCData &data); }; DECLARE_REMOTE_PROTOCOL(JVC) diff --git a/esphome/components/remote_base/keeloq_protocol.h b/esphome/components/remote_base/keeloq_protocol.h index 432313b87b..335fbd164b 100644 --- a/esphome/components/remote_base/keeloq_protocol.h +++ b/esphome/components/remote_base/keeloq_protocol.h @@ -24,9 +24,9 @@ struct KeeloqData { class KeeloqProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const KeeloqData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const KeeloqData &data) override; + void encode(RemoteTransmitData *dst, const KeeloqData &data); + optional decode(RemoteReceiveData src); + void dump(const KeeloqData &data); }; DECLARE_REMOTE_PROTOCOL(Keeloq) diff --git a/esphome/components/remote_base/lg_protocol.h b/esphome/components/remote_base/lg_protocol.h index 9715974995..91dfbadb0c 100644 --- a/esphome/components/remote_base/lg_protocol.h +++ b/esphome/components/remote_base/lg_protocol.h @@ -16,9 +16,9 @@ struct LGData { class LGProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const LGData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const LGData &data) override; + void encode(RemoteTransmitData *dst, const LGData &data); + optional decode(RemoteReceiveData src); + void dump(const LGData &data); }; DECLARE_REMOTE_PROTOCOL(LG) diff --git a/esphome/components/remote_base/magiquest_protocol.h b/esphome/components/remote_base/magiquest_protocol.h index 18662ec759..f0d2410fe2 100644 --- a/esphome/components/remote_base/magiquest_protocol.h +++ b/esphome/components/remote_base/magiquest_protocol.h @@ -27,9 +27,9 @@ struct MagiQuestData { class MagiQuestProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const MagiQuestData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const MagiQuestData &data) override; + void encode(RemoteTransmitData *dst, const MagiQuestData &data); + optional decode(RemoteReceiveData src); + void dump(const MagiQuestData &data); }; DECLARE_REMOTE_PROTOCOL(MagiQuest) diff --git a/esphome/components/remote_base/midea_protocol.h b/esphome/components/remote_base/midea_protocol.h index 47bad6826f..85bbef1cb1 100644 --- a/esphome/components/remote_base/midea_protocol.h +++ b/esphome/components/remote_base/midea_protocol.h @@ -67,9 +67,9 @@ class MideaData { class MideaProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const MideaData &src) override; - optional decode(RemoteReceiveData src) override; - void dump(const MideaData &data) override; + void encode(RemoteTransmitData *dst, const MideaData &src); + optional decode(RemoteReceiveData src); + void dump(const MideaData &data); }; DECLARE_REMOTE_PROTOCOL(Midea) diff --git a/esphome/components/remote_base/mirage_protocol.h b/esphome/components/remote_base/mirage_protocol.h index c967e72f13..a37fb93f4f 100644 --- a/esphome/components/remote_base/mirage_protocol.h +++ b/esphome/components/remote_base/mirage_protocol.h @@ -13,9 +13,9 @@ struct MirageData { class MirageProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const MirageData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const MirageData &data) override; + void encode(RemoteTransmitData *dst, const MirageData &data); + optional decode(RemoteReceiveData src); + void dump(const MirageData &data); protected: void encode_byte_(RemoteTransmitData *dst, uint8_t item); diff --git a/esphome/components/remote_base/nec_protocol.h b/esphome/components/remote_base/nec_protocol.h index 7b310e8ba5..1337f7a8b3 100644 --- a/esphome/components/remote_base/nec_protocol.h +++ b/esphome/components/remote_base/nec_protocol.h @@ -14,9 +14,9 @@ struct NECData { class NECProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const NECData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const NECData &data) override; + void encode(RemoteTransmitData *dst, const NECData &data); + optional decode(RemoteReceiveData src); + void dump(const NECData &data); }; DECLARE_REMOTE_PROTOCOL(NEC) diff --git a/esphome/components/remote_base/nexa_protocol.h b/esphome/components/remote_base/nexa_protocol.h index ebcd2a2c11..ebf85387b0 100644 --- a/esphome/components/remote_base/nexa_protocol.h +++ b/esphome/components/remote_base/nexa_protocol.h @@ -24,9 +24,9 @@ class NexaProtocol : public RemoteProtocol { void zero(RemoteTransmitData *dst) const; void sync(RemoteTransmitData *dst) const; - void encode(RemoteTransmitData *dst, const NexaData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const NexaData &data) override; + void encode(RemoteTransmitData *dst, const NexaData &data); + optional decode(RemoteReceiveData src); + void dump(const NexaData &data); }; DECLARE_REMOTE_PROTOCOL(Nexa) diff --git a/esphome/components/remote_base/panasonic_protocol.h b/esphome/components/remote_base/panasonic_protocol.h index d13c0f2798..84df3c08b7 100644 --- a/esphome/components/remote_base/panasonic_protocol.h +++ b/esphome/components/remote_base/panasonic_protocol.h @@ -16,9 +16,9 @@ struct PanasonicData { class PanasonicProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const PanasonicData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const PanasonicData &data) override; + void encode(RemoteTransmitData *dst, const PanasonicData &data); + optional decode(RemoteReceiveData src); + void dump(const PanasonicData &data); }; DECLARE_REMOTE_PROTOCOL(Panasonic) diff --git a/esphome/components/remote_base/pioneer_protocol.h b/esphome/components/remote_base/pioneer_protocol.h index 514ab67501..d02bd3451f 100644 --- a/esphome/components/remote_base/pioneer_protocol.h +++ b/esphome/components/remote_base/pioneer_protocol.h @@ -13,9 +13,9 @@ struct PioneerData { class PioneerProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const PioneerData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const PioneerData &data) override; + void encode(RemoteTransmitData *dst, const PioneerData &data); + optional decode(RemoteReceiveData src); + void dump(const PioneerData &data); }; DECLARE_REMOTE_PROTOCOL(Pioneer) diff --git a/esphome/components/remote_base/pronto_protocol.h b/esphome/components/remote_base/pronto_protocol.h index f4f6b2144d..bfd04c5cd9 100644 --- a/esphome/components/remote_base/pronto_protocol.h +++ b/esphome/components/remote_base/pronto_protocol.h @@ -30,9 +30,9 @@ class ProntoProtocol : public RemoteProtocol { std::string compensate_and_dump_sequence_(const RawTimings &data, uint16_t timebase); public: - void encode(RemoteTransmitData *dst, const ProntoData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const ProntoData &data) override; + void encode(RemoteTransmitData *dst, const ProntoData &data); + optional decode(RemoteReceiveData src); + void dump(const ProntoData &data); }; DECLARE_REMOTE_PROTOCOL(Pronto) diff --git a/esphome/components/remote_base/rc5_protocol.h b/esphome/components/remote_base/rc5_protocol.h index dbb89e41c6..f6f0f33c6e 100644 --- a/esphome/components/remote_base/rc5_protocol.h +++ b/esphome/components/remote_base/rc5_protocol.h @@ -14,9 +14,9 @@ struct RC5Data { class RC5Protocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const RC5Data &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const RC5Data &data) override; + void encode(RemoteTransmitData *dst, const RC5Data &data); + optional decode(RemoteReceiveData src); + void dump(const RC5Data &data); }; DECLARE_REMOTE_PROTOCOL(RC5) diff --git a/esphome/components/remote_base/rc6_protocol.h b/esphome/components/remote_base/rc6_protocol.h index fda9d98ecb..c4a2e8529b 100644 --- a/esphome/components/remote_base/rc6_protocol.h +++ b/esphome/components/remote_base/rc6_protocol.h @@ -15,9 +15,9 @@ struct RC6Data { class RC6Protocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const RC6Data &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const RC6Data &data) override; + void encode(RemoteTransmitData *dst, const RC6Data &data); + optional decode(RemoteReceiveData src); + void dump(const RC6Data &data); }; DECLARE_REMOTE_PROTOCOL(RC6) diff --git a/esphome/components/remote_base/rc_switch_protocol.cpp b/esphome/components/remote_base/rc_switch_protocol.cpp index 612558ca1c..2565eb4fbe 100644 --- a/esphome/components/remote_base/rc_switch_protocol.cpp +++ b/esphome/components/remote_base/rc_switch_protocol.cpp @@ -5,26 +5,6 @@ namespace esphome::remote_base { static const char *const TAG = "remote.rc_switch"; -const RCSwitchBase RC_SWITCH_PROTOCOLS[9] = {RCSwitchBase(0, 0, 0, 0, 0, 0, false), - RCSwitchBase(350, 10850, 350, 1050, 1050, 350, false), - RCSwitchBase(650, 6500, 650, 1300, 1300, 650, false), - RCSwitchBase(3000, 7100, 400, 1100, 900, 600, false), - RCSwitchBase(380, 2280, 380, 1140, 1140, 380, false), - RCSwitchBase(3000, 7000, 500, 1000, 1000, 500, false), - RCSwitchBase(10350, 450, 450, 900, 900, 450, true), - RCSwitchBase(300, 9300, 150, 900, 900, 150, false), - RCSwitchBase(250, 2500, 250, 1250, 250, 250, false)}; - -RCSwitchBase::RCSwitchBase(uint32_t sync_high, uint32_t sync_low, uint32_t zero_high, uint32_t zero_low, - uint32_t one_high, uint32_t one_low, bool inverted) - : sync_high_(sync_high), - sync_low_(sync_low), - zero_high_(zero_high), - zero_low_(zero_low), - one_high_(one_high), - one_low_(one_low), - inverted_(inverted) {} - void RCSwitchBase::one(RemoteTransmitData *dst) const { if (!this->inverted_) { dst->mark(this->one_high_); diff --git a/esphome/components/remote_base/rc_switch_protocol.h b/esphome/components/remote_base/rc_switch_protocol.h index 3224c04fb2..46d624f4ba 100644 --- a/esphome/components/remote_base/rc_switch_protocol.h +++ b/esphome/components/remote_base/rc_switch_protocol.h @@ -16,9 +16,16 @@ class RCSwitchBase { public: using ProtocolData = RCSwitchData; - RCSwitchBase() = default; - RCSwitchBase(uint32_t sync_high, uint32_t sync_low, uint32_t zero_high, uint32_t zero_low, uint32_t one_high, - uint32_t one_low, bool inverted); + constexpr RCSwitchBase() = default; + constexpr RCSwitchBase(uint32_t sync_high, uint32_t sync_low, uint32_t zero_high, uint32_t zero_low, + uint32_t one_high, uint32_t one_low, bool inverted) + : sync_high_(sync_high), + sync_low_(sync_low), + zero_high_(zero_high), + zero_low_(zero_low), + one_high_(one_high), + one_low_(one_low), + inverted_(inverted) {} void one(RemoteTransmitData *dst) const; @@ -61,7 +68,18 @@ class RCSwitchBase { bool inverted_{}; }; -extern const RCSwitchBase RC_SWITCH_PROTOCOLS[9]; +// Constant-initialized: no global constructor, and in flash on platforms that map .rodata there +inline constexpr RCSwitchBase RC_SWITCH_PROTOCOLS[] = { + {0, 0, 0, 0, 0, 0, false}, + {350, 10850, 350, 1050, 1050, 350, false}, + {650, 6500, 650, 1300, 1300, 650, false}, + {3000, 7100, 400, 1100, 900, 600, false}, + {380, 2280, 380, 1140, 1140, 380, false}, + {3000, 7000, 500, 1000, 1000, 500, false}, + {10350, 450, 450, 900, 900, 450, true}, + {300, 9300, 150, 900, 900, 150, false}, + {250, 2500, 250, 1250, 250, 250, false}, +}; uint64_t decode_binary_string(const std::string &data); diff --git a/esphome/components/remote_base/remote_base.cpp b/esphome/components/remote_base/remote_base.cpp index 4d9bc55f21..c922891aaf 100644 --- a/esphome/components/remote_base/remote_base.cpp +++ b/esphome/components/remote_base/remote_base.cpp @@ -99,29 +99,30 @@ bool RemoteReceiverBinarySensorBase::on_receive(RemoteReceiveData src) { /* RemoteReceiverBase */ +#ifdef REMOTE_BASE_DUMPER_COUNT void RemoteReceiverBase::register_dumper(RemoteReceiverDumperBase *dumper) { if (dumper->is_secondary()) { - this->secondary_dumpers_.push_back(dumper); + this->secondary_dumper_ = dumper; } else { this->dumpers_.push_back(dumper); } } +#endif -void RemoteReceiverBase::call_listeners_() { +void RemoteReceiverBase::call_listeners_dumpers_() { +#ifdef REMOTE_BASE_LISTENER_COUNT for (auto *listener : this->listeners_) listener->on_receive(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_)); -} - -void RemoteReceiverBase::call_dumpers_() { +#endif +#ifdef REMOTE_BASE_DUMPER_COUNT bool success = false; for (auto *dumper : this->dumpers_) { if (dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_))) success = true; } - if (!success) { - for (auto *dumper : this->secondary_dumpers_) - dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_)); - } + if (!success && this->secondary_dumper_ != nullptr) + this->secondary_dumper_->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_)); +#endif } void RemoteReceiverBinarySensorBase::dump_config() { LOG_BINARY_SENSOR("", "Remote Receiver Binary Sensor", this); } diff --git a/esphome/components/remote_base/remote_base.h b/esphome/components/remote_base/remote_base.h index 4e2ed4b71c..9ad6785df2 100644 --- a/esphome/components/remote_base/remote_base.h +++ b/esphome/components/remote_base/remote_base.h @@ -7,6 +7,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/hal.h" +#include "esphome/core/helpers.h" namespace esphome::remote_base { @@ -194,24 +195,27 @@ class RemoteReceiverDumperBase { class RemoteReceiverBase : public RemoteComponentBase { public: RemoteReceiverBase(InternalGPIOPin *pin) : RemoteComponentBase(pin) {} +#ifdef REMOTE_BASE_LISTENER_COUNT void register_listener(RemoteReceiverListener *listener) { this->listeners_.push_back(listener); } +#endif +#ifdef REMOTE_BASE_DUMPER_COUNT void register_dumper(RemoteReceiverDumperBase *dumper); +#endif void set_tolerance(uint32_t tolerance, ToleranceMode tolerance_mode) { this->tolerance_ = tolerance; this->tolerance_mode_ = tolerance_mode; } protected: - void call_listeners_(); - void call_dumpers_(); - void call_listeners_dumpers_() { - this->call_listeners_(); - this->call_dumpers_(); - } + void call_listeners_dumpers_(); - std::vector listeners_; - std::vector dumpers_; - std::vector secondary_dumpers_; +#ifdef REMOTE_BASE_LISTENER_COUNT + StaticVector listeners_; +#endif +#ifdef REMOTE_BASE_DUMPER_COUNT + StaticVector dumpers_; + RemoteReceiverDumperBase *secondary_dumper_{nullptr}; // runs only when no primary dumper matched +#endif RawTimings temp_; uint32_t tolerance_{25}; ToleranceMode tolerance_mode_{TOLERANCE_MODE_PERCENTAGE}; @@ -229,12 +233,10 @@ class RemoteReceiverBinarySensorBase : public binary_sensor::BinarySensorInitial /* TEMPLATES */ +// Protocols are used only through their concrete type; encode/decode/dump stay non-virtual so unused ones link out template class RemoteProtocol { public: using ProtocolData = T; - virtual void encode(RemoteTransmitData *dst, const ProtocolData &data) = 0; - virtual optional decode(RemoteReceiveData src) = 0; - virtual void dump(const ProtocolData &data) = 0; }; template class RemoteReceiverBinarySensor : public RemoteReceiverBinarySensorBase { diff --git a/esphome/components/remote_base/roomba_protocol.h b/esphome/components/remote_base/roomba_protocol.h index 3582dac398..8db025f812 100644 --- a/esphome/components/remote_base/roomba_protocol.h +++ b/esphome/components/remote_base/roomba_protocol.h @@ -12,9 +12,9 @@ struct RoombaData { class RoombaProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const RoombaData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const RoombaData &data) override; + void encode(RemoteTransmitData *dst, const RoombaData &data); + optional decode(RemoteReceiveData src); + void dump(const RoombaData &data); }; DECLARE_REMOTE_PROTOCOL(Roomba) diff --git a/esphome/components/remote_base/samsung36_protocol.h b/esphome/components/remote_base/samsung36_protocol.h index 4f15d906e7..df4e1af8d8 100644 --- a/esphome/components/remote_base/samsung36_protocol.h +++ b/esphome/components/remote_base/samsung36_protocol.h @@ -16,9 +16,9 @@ struct Samsung36Data { class Samsung36Protocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const Samsung36Data &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const Samsung36Data &data) override; + void encode(RemoteTransmitData *dst, const Samsung36Data &data); + optional decode(RemoteReceiveData src); + void dump(const Samsung36Data &data); }; DECLARE_REMOTE_PROTOCOL(Samsung36) diff --git a/esphome/components/remote_base/samsung_protocol.h b/esphome/components/remote_base/samsung_protocol.h index bb234d681d..dfa22ff85c 100644 --- a/esphome/components/remote_base/samsung_protocol.h +++ b/esphome/components/remote_base/samsung_protocol.h @@ -14,9 +14,9 @@ struct SamsungData { class SamsungProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const SamsungData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const SamsungData &data) override; + void encode(RemoteTransmitData *dst, const SamsungData &data); + optional decode(RemoteReceiveData src); + void dump(const SamsungData &data); }; DECLARE_REMOTE_PROTOCOL(Samsung) diff --git a/esphome/components/remote_base/sony_protocol.h b/esphome/components/remote_base/sony_protocol.h index eb873e8b7d..f83b2908b6 100644 --- a/esphome/components/remote_base/sony_protocol.h +++ b/esphome/components/remote_base/sony_protocol.h @@ -16,9 +16,9 @@ struct SonyData { class SonyProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const SonyData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const SonyData &data) override; + void encode(RemoteTransmitData *dst, const SonyData &data); + optional decode(RemoteReceiveData src); + void dump(const SonyData &data); }; DECLARE_REMOTE_PROTOCOL(Sony) diff --git a/esphome/components/remote_base/symphony_protocol.h b/esphome/components/remote_base/symphony_protocol.h index 7caf5eab86..40a5c2daec 100644 --- a/esphome/components/remote_base/symphony_protocol.h +++ b/esphome/components/remote_base/symphony_protocol.h @@ -17,9 +17,9 @@ struct SymphonyData { class SymphonyProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const SymphonyData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const SymphonyData &data) override; + void encode(RemoteTransmitData *dst, const SymphonyData &data); + optional decode(RemoteReceiveData src); + void dump(const SymphonyData &data); }; DECLARE_REMOTE_PROTOCOL(Symphony) diff --git a/esphome/components/remote_base/toshiba_ac_protocol.h b/esphome/components/remote_base/toshiba_ac_protocol.h index 8a853005ac..35d5af314c 100644 --- a/esphome/components/remote_base/toshiba_ac_protocol.h +++ b/esphome/components/remote_base/toshiba_ac_protocol.h @@ -14,9 +14,9 @@ struct ToshibaAcData { class ToshibaAcProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const ToshibaAcData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const ToshibaAcData &data) override; + void encode(RemoteTransmitData *dst, const ToshibaAcData &data); + optional decode(RemoteReceiveData src); + void dump(const ToshibaAcData &data); }; DECLARE_REMOTE_PROTOCOL(ToshibaAc) diff --git a/esphome/components/remote_base/toto_protocol.h b/esphome/components/remote_base/toto_protocol.h index 285c9f2125..8e965a5c73 100644 --- a/esphome/components/remote_base/toto_protocol.h +++ b/esphome/components/remote_base/toto_protocol.h @@ -16,9 +16,9 @@ struct TotoData { class TotoProtocol : public RemoteProtocol { public: - void encode(RemoteTransmitData *dst, const TotoData &data) override; - optional decode(RemoteReceiveData src) override; - void dump(const TotoData &data) override; + void encode(RemoteTransmitData *dst, const TotoData &data); + optional decode(RemoteReceiveData src); + void dump(const TotoData &data); }; DECLARE_REMOTE_PROTOCOL(Toto) diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index 6e8c73d331..b2fd87165e 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -221,11 +221,11 @@ async def to_code(config: ConfigType) -> None: dumpers = await remote_base.build_dumpers(config[CONF_DUMP]) for dumper in dumpers: - cg.add(var.register_dumper(dumper)) + remote_base.add_dumper(var, dumper) triggers = await remote_base.build_triggers(config) for trigger in triggers: - cg.add(var.register_listener(trigger)) + remote_base.add_listener(var, trigger) await cg.register_component(var, config) cg.add( diff --git a/esphome/core/defines.h b/esphome/core/defines.h index c3b16d833a..39e958d49c 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -137,6 +137,8 @@ #define MICRONOVA_LISTENER_COUNT 1 #define USE_MICRONOVA_WRITER #define MK2PVROUTER_LISTENER_COUNT 1 +#define REMOTE_BASE_DUMPER_COUNT 1 +#define REMOTE_BASE_LISTENER_COUNT 1 #define SERIAL_PROXY_COUNT 2 #define SNTP_SERVER_COUNT 3 #define USE_MEDIA_PLAYER diff --git a/tests/component_tests/remote_receiver/__init__.py b/tests/component_tests/remote_receiver/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/component_tests/remote_receiver/config/receiver_bare.yaml b/tests/component_tests/remote_receiver/config/receiver_bare.yaml new file mode 100644 index 0000000000..b474194801 --- /dev/null +++ b/tests/component_tests/remote_receiver/config/receiver_bare.yaml @@ -0,0 +1,9 @@ +esphome: + name: test + +esp32: + board: esp32dev + +remote_receiver: + - id: rcvr + pin: GPIO4 diff --git a/tests/component_tests/remote_receiver/config/receiver_with_dumpers.yaml b/tests/component_tests/remote_receiver/config/receiver_with_dumpers.yaml new file mode 100644 index 0000000000..32c1b07f57 --- /dev/null +++ b/tests/component_tests/remote_receiver/config/receiver_with_dumpers.yaml @@ -0,0 +1,24 @@ +esphome: + name: test + +esp32: + board: esp32dev + +logger: + +remote_receiver: + - id: rcvr + pin: GPIO4 + dump: + - nec + - rc_switch + on_nec: + then: + - logger.log: nec + +binary_sensor: + - platform: remote_receiver + name: Remote Input + nec: + address: 0x1234 + command: 0x5678 diff --git a/tests/component_tests/remote_receiver/config/receiver_with_proxies.yaml b/tests/component_tests/remote_receiver/config/receiver_with_proxies.yaml new file mode 100644 index 0000000000..66f2d01046 --- /dev/null +++ b/tests/component_tests/remote_receiver/config/receiver_with_proxies.yaml @@ -0,0 +1,20 @@ +esphome: + name: test + +esp32: + board: esp32dev + +remote_receiver: + - id: rcvr + pin: GPIO4 + +infrared: + - platform: ir_rf_proxy + name: IR Receiver + remote_receiver_id: rcvr + +radio_frequency: + - platform: ir_rf_proxy + name: RF Receiver + frequency: 433.92MHz + remote_receiver_id: rcvr diff --git a/tests/component_tests/remote_receiver/test_slot_counts.py b/tests/component_tests/remote_receiver/test_slot_counts.py new file mode 100644 index 0000000000..7fe26fae8b --- /dev/null +++ b/tests/component_tests/remote_receiver/test_slot_counts.py @@ -0,0 +1,36 @@ +"""Listener and dumper StaticVector sizes come from codegen slot counts.""" + +from collections.abc import Callable +from pathlib import Path + +from ..helpers import get_define_value + + +def test_dumper_and_listener_counts( + generate_main: Callable[[str | Path], str], + component_config_path: Callable[[str], Path], +) -> None: + generate_main(component_config_path("receiver_with_dumpers.yaml")) + # nec and rc_switch dumpers + assert get_define_value("REMOTE_BASE_DUMPER_COUNT") == "2" + # on_nec trigger plus the remote_receiver binary sensor + assert get_define_value("REMOTE_BASE_LISTENER_COUNT") == "2" + + +def test_bare_receiver_emits_no_counts( + generate_main: Callable[[str | Path], str], + component_config_path: Callable[[str], Path], +) -> None: + generate_main(component_config_path("receiver_bare.yaml")) + assert get_define_value("REMOTE_BASE_DUMPER_COUNT") is None + assert get_define_value("REMOTE_BASE_LISTENER_COUNT") is None + + +def test_proxy_receivers_count_as_listeners( + generate_main: Callable[[str | Path], str], + component_config_path: Callable[[str], Path], +) -> None: + generate_main(component_config_path("receiver_with_proxies.yaml")) + # infrared and radio_frequency ir_rf_proxy platforms each listen + assert get_define_value("REMOTE_BASE_LISTENER_COUNT") == "2" + assert get_define_value("REMOTE_BASE_DUMPER_COUNT") is None