From 0425fa77569e4d39c783b0595acecbf353beb445 Mon Sep 17 00:00:00 2001 From: Maxim Prokhorov Date: Wed, 26 Aug 2020 16:46:41 +0300 Subject: [PATCH] rfb receiver lock for multiple relays --- code/espurna/rfbridge.cpp | 40 ++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/code/espurna/rfbridge.cpp b/code/espurna/rfbridge.cpp index 0f9c9197..cbda1a82 100644 --- a/code/espurna/rfbridge.cpp +++ b/code/espurna/rfbridge.cpp @@ -20,6 +20,7 @@ Copyright (C) 2016-2019 by Xose PĂ©rez BrokerBind(RfbridgeBroker); #include +#include #include #include #include @@ -82,8 +83,14 @@ struct RfbLearn { bool status; }; +// Usage depends on the implementation. Will either: +// - efm8bb1: wait until learn OK / TIMEOUT code +// - rc-switch: receiver loop will check `ts` vs RFB_LEARN_TIMEOUT static std::unique_ptr _rfb_learn; +// Individual lock for the relay, prevent rfbStatus from re-sending the code we just received +static std::bitset _rfb_relay_status_lock; + #endif // RELAY_SUPPORT // ----------------------------------------------------------------------------- @@ -388,8 +395,6 @@ bool _rfbCompare(const char* lhs, const char* rhs, size_t length) { #if RELAY_SUPPORT -static bool _rfb_status_lock = false; - // try to find the 'code' saves as either rfbON# or rfbOFF# // // **always** expect full length code as input to simplify comparison @@ -477,13 +482,12 @@ void _rfbLearnFromString(std::unique_ptr& learn, const char* buffer) { } bool _rfbRelayHandler(const char* buffer, bool locked = false) { - _rfb_status_lock = locked; - bool result { false }; auto match = _rfbMatch(buffer); if (match.ok()) { DEBUG_MSG_P(PSTR("[RF] Matched with the relay ID %u\n"), match.id); + _rfb_relay_status_lock.set(match.id, locked); switch (match.status) { case PayloadStatus::On: @@ -499,8 +503,6 @@ bool _rfbRelayHandler(const char* buffer, bool locked = false) { } } - _rfb_status_lock = false; - return result; } @@ -589,7 +591,7 @@ void _rfbParse(uint8_t code, const std::vector& payload) { if (CodeLearnOk == code) { _rfbLearnFromString(_rfb_learn, buffer); } else { - _rfbRelayHandler(buffer); + _rfbRelayHandler(buffer, true); } #endif @@ -836,7 +838,7 @@ void _rfbReceiveImpl() { if (_rfb_learn) { _rfbLearnFromReceived(_rfb_learn, buffer); } else { - _rfbRelayHandler(buffer); + _rfbRelayHandler(buffer, true); } #endif @@ -973,8 +975,8 @@ void _rfbMqttCallback(unsigned int type, const char * topic, char * payload) { // we *sometimes* want to check the code against available rfbON / rfbOFF // e.g. in case we want to control some external device and have an external remote. // - when remote press happens, relays stay in sync when we receive the code via the processing loop - // - when we send the code here, we never register it as *sent*,, thus relays need to be made in sync manually - if (!_rfbRelayHandler(payload, /* locked = */ true)) { + // - when we send the code here, we never register it as *sent*, thus relays need to be made in sync manually + if (!_rfbRelayHandler(payload)) { #endif _rfbSendFromPayload(payload); #if RELAY_SUPPORT @@ -1119,15 +1121,19 @@ String rfbRetrieve(unsigned char id, bool status) { } void rfbStatus(unsigned char id, bool status) { - // ref. receiver loop, we need to protect ourselves from re-sending the code we received to turn this relay ID on / off - if (_rfb_status_lock) { - return; + // TODO: This is a left-over from the old implementation. Right now we set this lock when relay handler + // is called within the receiver, while this is called from either relayStatus or relay loop calling + // this via provider callback. This prevents us from re-sending the code we just received. + // TODO: Consider having 'origin' of the relay change. Either supply relayStatus with an additional arg, + // or track these statuses directly. + if (!_rfb_relay_status_lock[id]) { + String value = rfbRetrieve(id, status); + if (value.length() && !(value.length() & 1)) { + _rfbSendFromPayload(value.c_str()); + } } - String value = rfbRetrieve(id, status); - if (value.length() && !(value.length() & 1)) { - _rfbSendFromPayload(value.c_str()); - } + _rfb_relay_status_lock[id] = false; } void rfbLearn(unsigned char id, bool status) {