1
0
mirror of https://github.com/esphome/esphome.git synced 2025-03-14 06:38:17 +00:00

[remote_base] NEC, binary sensor add suport for button hold / repeat codes

This commit is contained in:
Djordje 2025-02-19 01:04:40 +01:00
parent 465590bb63
commit da8ba7c95a
2 changed files with 72 additions and 2 deletions

View File

@ -184,5 +184,46 @@ std::string NECProtocol::get_protocol_type_and_fields(const NECData &data) const
return debug_message;
}
bool NECBinarySensor::matches(RemoteReceiveData src) {
auto proto = NECProtocol();
auto res = proto.decode(src);
if (!res.has_value()) {
return false;
}
switch (res.value().type) {
case NECCodeType::FRAME_WITH_REPEATS:
// Set waiting to true only if currently not waiting and this is our desired frame.
this->waiting_for_repeat_code_ = (!this->waiting_for_repeat_code_ && (res.value() == this->data_));
break;
case NECCodeType::REPEATS_ONLY:
// Stay waiting only if we were already waiting and we got a valid repeat code.
this->waiting_for_repeat_code_ = (this->waiting_for_repeat_code_ && (res.value() == NEC_REPEAT_CODE_DATA));
break;
default:
this->waiting_for_repeat_code_ = false;
break;
}
return this->waiting_for_repeat_code_;
}
bool NECBinarySensor::on_receive(RemoteReceiveData src) {
if (!this->matches(src)) {
return false;
}
this->publish_state(true);
this->set_timeout("repeat", this->repeat_timeout_ms_, [this]() {
this->waiting_for_repeat_code_ = false;
this->publish_state(false);
});
return true;
}
} // namespace remote_base
} // namespace esphome

View File

@ -50,7 +50,7 @@ struct NECData {
};
};
/// @brief Predefined single repeat code `NECData` returned by `NECProtocol::decode`
/// @brief Predefined single repeat code `NECData` returned by `NECProtocol::decode(RemoteReceiveData)`
static const NECData NEC_REPEAT_CODE_DATA = {{0}, {0}, 1, NECCodeType::REPEATS_ONLY};
class NECProtocol : public RemoteProtocol<NECData> {
@ -92,7 +92,36 @@ class NECProtocol : public RemoteProtocol<NECData> {
std::string get_protocol_type_and_fields(const NECData &data) const;
};
DECLARE_REMOTE_PROTOCOL(NEC)
class NECBinarySensor : public RemoteReceiverBinarySensor<NECProtocol> {
public:
NECBinarySensor() : RemoteReceiverBinarySensor<NECProtocol>() {}
/// @brief Checks if the incoming data matches this sensor's expected NEC code.
/// @details
/// - If not currently waiting for a repeat code, only a matching new frame sets the waiting state.
/// - If waiting for a repeat code, only a valid repeat code keeps the sensor active.
/// - Otherwise, the sensor stops waiting.
/// @param[in] src The raw IR data to process.
/// @return True if the decoded data matches the expected code and is valid in the current state; false otherwise.
bool matches(RemoteReceiveData src) override;
/// @brief Called when new data arrives. If it matches, turn the sensor on and set a timeout to turn it off.
/// @details
/// - Internally calls `NECBinarySensor::matches(RemoteReceiveData)`.
/// - If a match occurs, publishes an "on" state and sets a timeout to revert to "off" if no repeat codes arrive.
/// @note The off state is published automatically when the timeout expires.
/// @param[in] src The raw IR data to process.
/// @return True if this data is handled and match found, false otherwise.
bool on_receive(RemoteReceiveData src) override;
protected:
/// @brief The timeout in milliseconds to wait for repeat codes before turning the sensor off.
uint8_t repeat_timeout_ms_{130};
/// @brief Indicates whether the sensor is currently expecting a repeat code.
bool waiting_for_repeat_code_{false};
};
using NECTrigger = RemoteReceiverTrigger<NECProtocol>;
using NECDumper = RemoteReceiverDumper<NECProtocol>;
template<typename... Ts> class NECAction : public RemoteTransmitterActionBase<Ts...> {
public: