From 2f616eef2c0b414c7683b69b2218ab76dcad59fc Mon Sep 17 00:00:00 2001 From: Subhash Chandra Date: Sat, 10 Jun 2023 18:23:02 +0530 Subject: [PATCH] make IRHVAC send incremental changes. (#18310) This change will allow mqtt messages simpler by allowing something like `publish cmnd/ir-bridge/IRHVAC {"Power": "On"}`. The simpler format is required for working with mqtt clients like iotMQTTPanel or similar on android. Limitations: - Requires full message be sent at-least once. I work around this with a `system#boot` rule - Gets messy with multiple devices. I have only one AC per room, and this doesn't doesn't interfere with other IR devices. TODO: - [ ] Change the build flag `INCREMENTAL_IRAC`to a `SetOption` - [ ] Persist `irac_prev_state` across reboots. - [ ] Support multiple devices. --- tasmota/include/i18n.h | 1 + .../xdrv_05_irremote_full.ino | 37 +++++++------------ 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/tasmota/include/i18n.h b/tasmota/include/i18n.h index 85dd46178..37be387fe 100644 --- a/tasmota/include/i18n.h +++ b/tasmota/include/i18n.h @@ -561,6 +561,7 @@ #define D_JSON_IRHVAC_STATE_MODE_SEND_ONLY "SendOnly" #define D_JSON_IRHVAC_STATE_MODE_STORE_ONLY "StoreOnly" #define D_JSON_IRHVAC_STATE_MODE_SEND_STORE "SendStore" + #define D_JSON_IRHVAC_INCREMENTAL "Incremental" #define D_JSON_IRRECEIVED "IrReceived" // Commands xdrv_06_snfbridge.ino diff --git a/tasmota/tasmota_xdrv_driver/xdrv_05_irremote_full.ino b/tasmota/tasmota_xdrv_driver/xdrv_05_irremote_full.ino index 025ec480c..e0671de1e 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_05_irremote_full.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_05_irremote_full.ino @@ -128,6 +128,8 @@ protected: // some ACs send toggle messages rather than state. we need to help IRremoteESP8266 keep track of the state // have a flag that is a variable, can be later used to convert this functionality to an option (as in SetOptionXX) bool irhvac_stateful = true; +bool irhvac_incremental = true; + stdAc::state_t irac_prev_state; // this implementations only keeps one state so if you use a single tasmota-ir device to command more than one AC it might not work // different modes on how to handle state when sending HVAC commands. needed for ACs with a differential/toggle protocol. @@ -438,6 +440,8 @@ const stdAc::fanspeed_t IrHvacFanSpeed[] PROGMEM = { stdAc::fanspeed_t::kAuto, uint32_t IrRemoteCmndIrHvacJson(void) { + // state is initialized to the IRremoteESP8266's state_t defaults anyway + // https://github.com/crankyoldgit/IRremoteESP8266/blob/v2.8.4/src/IRsend.h#L97-L116 stdAc::state_t state; //AddLog(LOG_LEVEL_DEBUG, PSTR("IRHVAC: Received %s"), XdrvMailbox.data); @@ -445,28 +449,13 @@ uint32_t IrRemoteCmndIrHvacJson(void) JsonParserObject root = parser.getRootObject(); if (!root) { return IE_INVALID_JSON; } - // from: https://github.com/crankyoldgit/IRremoteESP8266/blob/master/examples/CommonAcControl/CommonAcControl.ino - state.protocol = decode_type_t::UNKNOWN; - state.model = 1; // Some A/C's have different models. Let's try using just 1. - state.command = stdAc::ac_command_t::kControlCommand; - state.mode = stdAc::opmode_t::kAuto; // Run in cool mode initially. - state.power = false; // Initially start with the unit off. - state.celsius = true; // Use Celsius for units of temp. False = Fahrenheit - state.degrees = 21.0f; // 21 degrees. - state.fanspeed = stdAc::fanspeed_t::kMedium; // Start with the fan at medium. - state.swingv = stdAc::swingv_t::kOff; // Don't swing the fan up or down. - state.swingh = stdAc::swingh_t::kOff; // Don't swing the fan left or right. - state.light = false; // Turn off any LED/Lights/Display that we can. - state.beep = false; // Turn off any beep from the A/C if we can. - state.econo = false; // Turn off any economy modes if we can. - state.filter = false; // Turn off any Ion/Mold/Health filters if we can. - state.turbo = false; // Don't use any turbo/powerful/etc modes. - state.quiet = false; // Don't use any quiet/silent/etc modes. - state.sleep = -1; // Don't set any sleep time or modes. - state.clean = false; // Turn off any Cleaning options if we can. - state.clock = -1; // Don't set any current time if we can avoid it. - state.iFeel = false; - state.sensorTemperature = kNoTempValue; // Don't set any sensor (ambient) temperature if not provided + bool incremental = strToBool(root[PSTR(D_JSON_IRHVAC_INCREMENTAL)], false); + + // TODO: add support for storing multiple states + if (incremental) + { + state = irac_prev_state; + } JsonParserToken val; if (val = root[PSTR(D_JSON_IRHVAC_VENDOR)]) { state.protocol = strToDecodeType(val.getStr()); } @@ -495,8 +484,8 @@ uint32_t IrRemoteCmndIrHvacJson(void) // AddLog(LOG_LEVEL_DEBUG, PSTR("model %d, mode %d, fanspeed %d, swingv %d, swingh %d"), // state.model, state.mode, state.fanspeed, state.swingv, state.swingh); - // if and how we should handle the state for IRremote - StateModes stateMode = StateModes::SEND_ONLY; // default + StateModes stateMode = incremental ? StateModes::SEND_STORE : StateModes::SEND_ONLY; + if (irhvac_stateful && (val = root[PSTR(D_JSON_IRHVAC_STATE_MODE)])) { stateMode = strToStateMode(val, stateMode); } // decode booleans