From 5f90c7c3bc1ac5563486c5d819eba701f003dacd Mon Sep 17 00:00:00 2001 From: Max Prokhorov Date: Sun, 7 Jun 2020 19:12:04 +0300 Subject: [PATCH] RPN: check relay status before triggering (#2268) * rpn: check status to avoid rescheduling * keep existing op, add name hint --- code/espurna/relay.cpp | 5 +++++ code/espurna/relay.h | 5 +++++ code/espurna/rpnrules.cpp | 33 ++++++++++++++++++++++++--------- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/code/espurna/relay.cpp b/code/espurna/relay.cpp index a7f4eadb..f8f36a3c 100644 --- a/code/espurna/relay.cpp +++ b/code/espurna/relay.cpp @@ -619,6 +619,11 @@ bool relayStatus(unsigned char id) { } +bool relayStatusTarget(unsigned char id) { + if (id >= _relays.size()) return false; + return _relays[id].target_status; +} + void relaySync(unsigned char id) { // No sync if none or only one relay diff --git a/code/espurna/relay.h b/code/espurna/relay.h index 2a462a9e..4ac69618 100644 --- a/code/espurna/relay.h +++ b/code/espurna/relay.h @@ -19,7 +19,12 @@ PayloadStatus relayParsePayload(const char * payload); bool relayStatus(unsigned char id, bool status, bool report, bool group_report); bool relayStatus(unsigned char id, bool status); + +// gets either current or target status, where current is the status that we are +// actually in and target is the status we would be, eventually, unless +// relayStatus(id, relayStatus()) is called bool relayStatus(unsigned char id); +bool relayStatusTarget(unsigned char id); void relayToggle(unsigned char id, bool report, bool group_report); void relayToggle(unsigned char id); diff --git a/code/espurna/rpnrules.cpp b/code/espurna/rpnrules.cpp index 4acc0323..68ad98c0 100644 --- a/code/espurna/rpnrules.cpp +++ b/code/espurna/rpnrules.cpp @@ -139,6 +139,23 @@ bool _rpnNtpFunc(rpn_context & ctxt, int (*func)(time_t)) { #endif +#if RELAY_SUPPORT + +bool _rpnRelayStatus(rpn_context & ctxt, bool force) { + float status, id; + rpn_stack_pop(ctxt, id); + rpn_stack_pop(ctxt, status); + + if (int(status) == 2) { + relayToggle(int(id)); + } else if (force || (relayStatusTarget(int(id)) != (int(status) == 1))) { + relayStatus(int(id), int(status) == 1); + } + return true; +} + +#endif + void _rpnDump() { float value; DEBUG_MSG_P(PSTR("[RPN] Stack:\n")); @@ -239,16 +256,14 @@ void _rpnInit() { // Accept relay number and numeric API status value (0, 1 and 2) #if RELAY_SUPPORT + // apply status and reset timers when called + rpn_operator_set(_rpn_ctxt, "relay_reset", 2, [](rpn_context & ctxt) { + return _rpnRelayStatus(ctxt, true); + }); + + // only update status when target status differs, keep running timers rpn_operator_set(_rpn_ctxt, "relay", 2, [](rpn_context & ctxt) { - float status, id; - rpn_stack_pop(ctxt, id); - rpn_stack_pop(ctxt, status); - if (int(status) == 2) { - relayToggle(int(id)); - } else { - relayStatus(int(id), int(status) == 1); - } - return true; + return _rpnRelayStatus(ctxt, false); }); #endif // RELAY_SUPPORT == 1