diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 9484b8f2a..2a479c086 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -379,11 +379,12 @@ enum TuyaSupportedFunctions { TUYA_MCU_FUNC_NONE, TUYA_MCU_FUNC_REL1_INV = 41, TUYA_MCU_FUNC_REL2_INV, TUYA_MCU_FUNC_REL3_INV, TUYA_MCU_FUNC_REL4_INV, TUYA_MCU_FUNC_REL5_INV, TUYA_MCU_FUNC_REL6_INV, TUYA_MCU_FUNC_REL7_INV, TUYA_MCU_FUNC_REL8_INV, TUYA_MCU_FUNC_LOWPOWER_MODE = 51, - TUYA_MCU_FUNC_FAN3 = 61, TUYA_MCU_FUNC_FAN4, TUYA_MCU_FUNC_FAN5, TUYA_MCU_FUNC_FAN6, + TUYA_MCU_FUNC_ENUM1 = 61, TUYA_MCU_FUNC_ENUM2, TUYA_MCU_FUNC_ENUM3, TUYA_MCU_FUNC_ENUM4, TUYA_MCU_FUNC_MOTOR_DIR = 97, TUYA_MCU_FUNC_ERROR = 98, TUYA_MCU_FUNC_DUMMY = 99, TUYA_MCU_FUNC_LAST = 255 + // IDs from 230 to 234 are reserved for internal use }; #endif // _TASMOTA_H_ diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index d567215d5..dd1c9abc8 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1485,7 +1485,6 @@ void HandleRoot(void) } #ifdef USE_TUYA_MCU if (IsModuleTuya()) { - uint8_t modeset = 0; if (AsModuleTuyaMS()) { WSContentSend_P(HTTP_TABLE100); WSContentSend_P(PSTR("
")); @@ -1493,18 +1492,6 @@ void HandleRoot(void) WSContentSend_P(HTTP_DEVICE_CONTROL, 26, TasmotaGlobal.devices_present + 1, (strlen(SettingsText(SET_BUTTON1 + TasmotaGlobal.devices_present))) ? SettingsText(SET_BUTTON1 + TasmotaGlobal.devices_present) : stemp, ""); WSContentSend_P(PSTR("")); - modeset = 1; - } - if (IsTuyaFanCtrl()) { - uint8_t device = TasmotaGlobal.devices_present + modeset; - WSContentSend_P(HTTP_TABLE100); - WSContentSend_P(PSTR("
")); - for (uint32_t i = device + 1; i <= (TuyaFanSpeeds() + device) + 1; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i - (device + 1)); - WSContentSend_P(HTTP_DEVICE_CONTROL, 16, i, - (strlen(SettingsText(SET_BUTTON1 + i))) ? SettingsText(SET_BUTTON1 + i) : stemp, ""); - } - WSContentSend_P(PSTR("")); } } #endif // USE_TUYA_MCU @@ -1580,29 +1567,15 @@ bool HandleRootStatusRefresh(void) #endif // USE_SONOFF_IFAN #ifdef USE_TUYA_MCU if (IsModuleTuya()) { - uint8_t FuncIdx = 0; - if (device <= TasmotaGlobal.devices_present) { - ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); - } else { - if (AsModuleTuyaMS() && device == TasmotaGlobal.devices_present + 1) { - uint8_t dpId = TuyaGetDpId(TUYA_MCU_FUNC_MODESET); - snprintf_P(svalue, sizeof(svalue), PSTR("Tuyasend4 %d,%d"), dpId, !TuyaModeSet()); - ExecuteCommand(svalue, SRC_WEBGUI); - } - if (IsTuyaFanCtrl()) { - uint8_t dpId = 0; - for (uint32_t i = 0; i <= 3; i++) { // Tuya Function FAN3 to FAN6 - if (TuyaGetDpId(TUYA_MCU_FUNC_FAN3 + i) != 0) { - dpId = TuyaGetDpId(TUYA_MCU_FUNC_FAN3 + i); - } - } - if ((AsModuleTuyaMS() && device != TasmotaGlobal.devices_present + 1) || !AsModuleTuyaMS()) { - if (AsModuleTuyaMS()) {FuncIdx = 1;} - snprintf_P(svalue, sizeof(svalue), PSTR("Tuyasend2 %d,%d"), dpId, (device - (TasmotaGlobal.devices_present + FuncIdx) - 1)); - ExecuteCommand(svalue, SRC_WEBGUI); - } - } + if (device <= TasmotaGlobal.devices_present) { + ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); + } else { + if (AsModuleTuyaMS() && device == TasmotaGlobal.devices_present + 1) { + uint8_t dpId = TuyaGetDpId(TUYA_MCU_FUNC_MODESET); + snprintf_P(svalue, sizeof(svalue), PSTR("Tuyasend4 %d,%d"), dpId, !TuyaModeSet()); + ExecuteCommand(svalue, SRC_WEBGUI); } + } } else { #endif // USE_TUYA_MCU #ifdef USE_SHUTTER @@ -1707,14 +1680,9 @@ bool HandleRootStatusRefresh(void) } #ifdef USE_TUYA_MCU if (IsModuleTuya()) { - uint32_t fanspeed = TuyaFanState(); uint32_t modeset = TuyaModeSet(); - if (IsTuyaFanCtrl() && !AsModuleTuyaMS()) { - WSContentSend_P(PSTR("
" D_JSON_IRHVAC_FANSPEED ": %d
"), fanspeed); - } else if (!IsTuyaFanCtrl() && AsModuleTuyaMS()) { + if (AsModuleTuyaMS()) { WSContentSend_P(PSTR("
" D_JSON_IRHVAC_MODE ": %d
"), modeset); - } else if (IsTuyaFanCtrl() && AsModuleTuyaMS()) { - WSContentSend_P(PSTR("
" D_JSON_IRHVAC_MODE ": %d - " D_JSON_IRHVAC_FANSPEED ": %d
"), modeset, fanspeed); } } #endif // USE_TUYA_MCU diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index 77b97be17..0c3b3bc33 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -56,8 +56,9 @@ TasmotaSerial *TuyaSerial = nullptr; struct TUYA { uint16_t Levels[5] = {0,0,0,0,0}; // Array to store the values of TuyaMCU channels - uint16_t Snapshot[5] = {0,0,0,0,0}; // Array to store a snapshot of Tasmota actual values for channels - char HSBColor[13]; // Stores HSB Color string in Hex format + uint16_t Snapshot[5] = {0,0,0,0,0}; // Array to store a snapshot of Tasmota actual channel values + uint16_t EnumState[4] = {0,0,0,0}; // Array to store up to four Enum type 4 values + char RGBColor[7] = "000000"; // Stores RGB Color string in Hex format uint16_t CTMin = 153; // Minimum CT level allowed - When SetOption82 is enabled will default to 200 uint16_t CTMax = 500; // Maximum CT level allowed - When SetOption82 is enabled will default to 380 bool ModeSet = false; // Controls 0 - Single Tone light, 1 - RGB Light @@ -81,11 +82,15 @@ struct TUYA { bool ignore_tuyareceived = false; // When a modeset changes ignore stat } Tuya; +#define D_CMND_TUYARGB "TuyaRGB" +#define D_CMND_ENUM "Enum" +#define D_CMND_ENUM_LIST "EnumList" + const char kTuyaCommand[] PROGMEM = "|" // No prefix - D_CMND_TUYA_MCU "|" D_CMND_TUYA_MCU_SEND_STATE; + D_CMND_TUYA_MCU "|" D_CMND_TUYA_MCU_SEND_STATE "|" D_CMND_TUYARGB "|" D_CMND_ENUM "|" D_CMND_ENUM_LIST; void (* const TuyaCommand[])(void) PROGMEM = { - &CmndTuyaMcu, &CmndTuyaSend + &CmndTuyaMcu, &CmndTuyaSend, &CmndTuyaRgb, &CmndEnum, &CmndEnumList }; /*********************************************************************************************\ @@ -101,34 +106,11 @@ bool AsModuleTuyaMS(void) // ModeSet Layout return ((TasmotaGlobal.light_type > LT_RGB) && TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0); } -bool IsTuyaFanCtrl(void) // Fan Speed Controller Layout -{ - return ((TuyaGetDpId(TUYA_MCU_FUNC_FAN3) != 0) || (TuyaGetDpId(TUYA_MCU_FUNC_FAN4) != 0) || - (TuyaGetDpId(TUYA_MCU_FUNC_FAN5) != 0) || (TuyaGetDpId(TUYA_MCU_FUNC_FAN6) != 0)); -} - bool TuyaModeSet(void) // ModeSet Status { return Tuya.ModeSet; } -uint8_t TuyaFanSpeeds(void) // Number of Fan Speeds for WebUI -{ - uint8_t FanSpeeds = 0; - for (uint32_t i = 0; i <= 3; i++) { - if (TuyaGetDpId(TUYA_MCU_FUNC_FAN3 + i) != 0) { - FanSpeeds = i + 2; - } - } - return FanSpeeds; -} - -uint8_t TuyaFanState(void) // Fan Speed Status -{ - return Tuya.FanState; -} -// Web Interface - /* TuyaSend dpId,data @@ -137,7 +119,7 @@ TuyaSend1 11,1 -> Sends boolean (Type 1) data 0/1 to dpId 11 (Max data length 1 TuyaSend2 11,100 -> Sends integer (Type 2) data 100 to dpId 11 (Max data length 4 bytes) TuyaSend2 11,0xAABBCCDD -> Sends 4 bytes (Type 2) data to dpId 11 (Max data length 4 bytes) TuyaSend3 11,ThisIsTheData -> Sends the supplied string (Type 3) to dpId 11 ( Max data length not-known) -TuyaSend4 11,1 -> Sends enum (Type 4) data 0/1/2/3/4/5 to dpId 11 (Max data length 1 bytes) +TuyaSend4 11,1 -> Sends enum (Type 4) data 0/1/2/3/4/5/6/7/8/9 to dpId 11 (Max data length 1 bytes) */ void CmndTuyaSend(void) { @@ -149,7 +131,7 @@ void CmndTuyaSend(void) { } else if (XdrvMailbox.index == 8) { TuyaRequestState(8); } else if (XdrvMailbox.index == 9) { // TuyaSend Topic Toggle - if (Settings.tuyamcu_topic) { Settings.tuyamcu_topic = 0; } else { Settings.tuyamcu_topic = 1; } + Settings.tuyamcu_topic = !Settings.tuyamcu_topic; AddLog_P(LOG_LEVEL_INFO, PSTR("TYA: TuyaMCU Stat Topic %s"), (Settings.tuyamcu_topic ? PSTR("enabled") : PSTR("disabled"))); } else { @@ -194,25 +176,26 @@ void CmndTuyaMcu(void) { } if (TuyaFuncIdValid(parm[0])) { - // TuyaAddMcuFunc(parm[0], parm[1]); - // TasmotaGlobal.restart_flag = 2; - // } else { - // AddLog_P(LOG_LEVEL_ERROR, PSTR("TYA: TuyaMcu Invalid function id=%d"), parm[0]); - // } bool DualDim; if (TUYA_MCU_FUNC_DIMMER2 == parm[0] && parm[1] != 0) { if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) != 0) { DualDim = true; } } else if (TUYA_MCU_FUNC_DIMMER == parm[0] && parm[1] != 0) { if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2) != 0) { DualDim = true; } } else if ((TUYA_MCU_FUNC_DIMMER == parm[0] && parm[1] == 0) || (TUYA_MCU_FUNC_DIMMER2 == parm[0] && parm[1] == 0)) { DualDim = false; }; - if (DualDim) { - if (TuyaGetDpId(TUYA_MCU_FUNC_CT) != 0) { TuyaAddMcuFunc(TUYA_MCU_FUNC_CT, 0); } // If the second dimmer is enabled CT, RGB or WHITE function must be removed + if (DualDim) { // If the second dimmer is enabled CT, RGB or WHITE function must be removed + if (TuyaGetDpId(TUYA_MCU_FUNC_CT) != 0) { TuyaAddMcuFunc(TUYA_MCU_FUNC_CT, 0); } if (TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0) { TuyaAddMcuFunc(TUYA_MCU_FUNC_RGB, 0); } if (TuyaGetDpId(TUYA_MCU_FUNC_WHITE) != 0) { TuyaAddMcuFunc(TUYA_MCU_FUNC_WHITE, 0); } Settings.flag3.pwm_multi_channels = 1; } else { Settings.flag3.pwm_multi_channels = 0; } TuyaAddMcuFunc(parm[0], parm[1]); TasmotaGlobal.restart_flag = 2; + if (TUYA_MCU_FUNC_RGB == parm[0] && parm[1] != 0) { + // if (Settings.tuya_fnid_map[235].dpid > 3) { + // Settings.tuya_fnid_map[235].fnid = 235; + // Settings.tuya_fnid_map[235].dpid = 0; + // } + } } else { AddLog_P(LOG_LEVEL_ERROR, PSTR("TYA: TuyaMcu Invalid function id=%d"), parm[0]); } @@ -232,6 +215,99 @@ void CmndTuyaMcu(void) { ResponseAppend_P(PSTR("]}")); } +void CmndTuyaRgb(void) { // Command to control the RGB format + + uint16_t payload = XdrvMailbox.payload; + + if (XdrvMailbox.data_len > 0) { + if (payload < 0 || payload > 3 || TuyaGetDpId(TUYA_MCU_FUNC_RGB) == 0) { + return; + } else { + if (payload != Settings.tuya_fnid_map[230].dpid) { // fnid 230 reserved for RGB + Settings.tuya_fnid_map[230].fnid = 230; + Settings.tuya_fnid_map[230].dpid = payload; + } + } + } + Response_P(PSTR("{\"" D_CMND_TUYARGB "\":%d}"), Settings.tuya_fnid_map[230].dpid); +} + +void CmndEnum(void) { // Command to control up to four type 4 Enum + uint16_t EnumIdx = XdrvMailbox.index; + int32_t payload = XdrvMailbox.payload; + + if (EnumIdx > 4 || TuyaGetDpId(TUYA_MCU_FUNC_ENUM1 + (EnumIdx-1)) == 0) { + return; + } + + if (XdrvMailbox.data_len > 0) { + if (payload < 0 || payload > Settings.tuya_fnid_map[EnumIdx + 230].dpid ) { + return; + } else { + if (payload != Tuya.EnumState[EnumIdx-1]) { + Tuya.EnumState[EnumIdx-1] = payload; + TuyaSendEnum(TuyaGetDpId(TUYA_MCU_FUNC_ENUM1 + (EnumIdx-1)), payload); + } + Response_P(PSTR("{\"" D_CMND_ENUM "%d\":%d}"), EnumIdx, Tuya.EnumState[EnumIdx-1]); + } + } else { + Response_P(PSTR("{\"" D_CMND_ENUM "\":{")); + bool added = false; + for (uint8_t i = 0; i <= 3; i++) { + if (TuyaGetDpId(TUYA_MCU_FUNC_ENUM1 + i) != 0) { + if (added) { + ResponseAppend_P(PSTR(",")); + } + ResponseAppend_P(PSTR("\"Enum%d\":%d"), i + 1, Tuya.EnumState[i]); // Returns the avtual values of Enum as list + added = true; + } + } + ResponseAppend_P(PSTR("}}")); + } +} + +void CmndEnumList(void) { // Command to declare the number of items in list for up to four type 4 enum. Min = 0, Max = 9, Default = 1 + + if (XdrvMailbox.data_len > 0) { + char *p; + uint8_t i = 0; + uint8_t parm[3] = { 0 }; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { + parm[i] = strtoul(str, nullptr, 0); + i++; + } + if ((parm[0] >= 1 && parm[0] <= 4) && (parm[1] >= 1 && parm[1] <= 9)) { + uint16_t idx = parm[0] + 230; // fnid 231, 232, 233 and 234 are reserved for enum + Settings.tuya_fnid_map[idx].fnid = idx; + Settings.tuya_fnid_map[idx].dpid = parm[1]; + } + } + if ((TuyaGetDpId(TUYA_MCU_FUNC_ENUM1) != 0) || (TuyaGetDpId(TUYA_MCU_FUNC_ENUM3) != 0) || + (TuyaGetDpId(TUYA_MCU_FUNC_ENUM3) != 0) || (TuyaGetDpId(TUYA_MCU_FUNC_ENUM4) != 0)) { + Response_P(PSTR("{\"" D_CMND_ENUM_LIST "\":{")); + bool added = false; + for (uint8_t i = 0; i <= 3; i++) { + if (TuyaGetDpId(TUYA_MCU_FUNC_ENUM1 + i) != 0) { + if (added) { + ResponseAppend_P(PSTR(",")); + if ( Settings.tuya_fnid_map[i + 231].dpid > 9 ) { Settings.tuya_fnid_map[i + 231].dpid = 1; } // default to 1 it the value exceed the range + } + ResponseAppend_P(PSTR("\"Enum%d\":%d"), i + 1, Settings.tuya_fnid_map[i + 231].dpid); // fnid 231, 232, 233 and 234 are reserved for Enum + added = true; + } + } + ResponseAppend_P(PSTR("}}")); + } else { return; } +} + +int StrCmpNoCase(char const *Str1, char const *Str2) // Compare RGB case sensistive strings +{ + for (;; Str1++, Str2++) { + int StrCmp = tolower((unsigned char)*Str1) - tolower((unsigned char)*Str2); + if (StrCmp != 0 || !*Str1) { return StrCmp; } + } +} + /*********************************************************************************************\ * Internal Functions \*********************************************************************************************/ @@ -274,7 +350,6 @@ void UpdateDevices() { } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { // Inverted Relay bitSet(TasmotaGlobal.rel_inverted, fnId - TUYA_MCU_FUNC_REL1_INV); } - } } } @@ -285,11 +360,10 @@ inline bool TuyaFuncIdValid(uint8_t fnId) { (fnId >= TUYA_MCU_FUNC_DIMMER && fnId <= TUYA_MCU_FUNC_REPORT2) || (fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_BATTERY_PERCENTAGE) || (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) || - (fnId >= TUYA_MCU_FUNC_FAN3 && fnId <= TUYA_MCU_FUNC_FAN6) || + (fnId >= TUYA_MCU_FUNC_ENUM1 && fnId <= TUYA_MCU_FUNC_ENUM4) || (fnId >= TUYA_MCU_FUNC_MOTOR_DIR && fnId <= TUYA_MCU_FUNC_DUMMY) || (fnId == TUYA_MCU_FUNC_LOWPOWER_MODE); } - uint8_t TuyaGetFuncId(uint8_t dpid) { for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { if (Settings.tuya_fnid_map[i].dpid == dpid) { @@ -413,7 +487,7 @@ bool TuyaSetChannels(void) uint16_t hue, TuyaData; uint8_t sat, bri; uint8_t TuyaIdx = 0; - char hex_char[13]; + char hex_char[15]; bool noupd = false; bool LightMode = TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0; uint8_t idx = 0; @@ -457,17 +531,45 @@ bool TuyaSetChannels(void) if (TasmotaGlobal.light_type >= LT_RGB) { + // There are two types of rgb format, configure the correct one using TuyaRGB command. + // The most common is 0HUE0SAT0BRI0 and the less common is RRGGBBFFFF6464 and sometimes both are case sensitive: + // 0 type 1 Uppercase - 00DF00DC0244 + // 1 Type 1 Lowercase - 008003e8037a + // 2 Type 2 Uppercase - 00FF00FFFF6464 + // 3 Type 2 Lowercase - 00e420ffff6464 + + uint8_t RGBType = Settings.tuya_fnid_map[230].dpid; // Select the type of RGB payload + char scolor[7]; + LightGetColor(scolor, 1); // Always get the color in hex format light_state.getHSB(&hue, &sat, &bri); sat = changeUIntScale(sat, 0, 255, 0, 100); bri = changeUIntScale(bri, 0, 255, 0, 100); - if (hue != Tuya.Snapshot[2] || sat != Tuya.Snapshot[3] || bri != Tuya.Snapshot[4]) { + + if ((RGBType > 1 && (StrCmpNoCase(scolor, Tuya.RGBColor) != 0)) || (RGBType <= 1 && ((hue != Tuya.Snapshot[2]) || + (sat != Tuya.Snapshot[3]) || (bri != Tuya.Snapshot[4])))) { + if ((LightMode && Tuya.ModeSet) || LT_RGB == TasmotaGlobal.light_type) { - snprintf_P(hex_char, sizeof(hex_char), PSTR("%04X%04X%04X"), hue, sat * 10, bri * 10); // Create a TuyaMCU readable RGB payload + if (TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0) { + switch (RGBType) { + case 0: // Uppercase Type 1 payload + snprintf_P(hex_char, sizeof(hex_char), PSTR("%04X%04X%04X"), hue, sat * 10, bri * 10); + break; + case 1: // Lowercase Type 1 payload + snprintf_P(hex_char, sizeof(hex_char), PSTR("%04x%04x%04x"), hue, sat * 10, bri * 10); + break; + case 2: // Uppercase Type 2 payload + snprintf_P(hex_char, sizeof(hex_char), PSTR("%sFFFF6464"), scolor); + break; + case 3: // Lowercase Type 2 payload + snprintf_P(hex_char, sizeof(hex_char), PSTR("%sffff6464"), LowerCase(scolor, scolor)); + break; + } + memcpy_P(Tuya.RGBColor, scolor, strlen(scolor)); + Tuya.Snapshot[2] = hue; + Tuya.Snapshot[3] = sat; + Tuya.Snapshot[4] = bri; + } LightSerialDuty(0, &hex_char[0], 3); - memcpy_P(Tuya.HSBColor, hex_char, strlen(hex_char)); - Tuya.Snapshot[2] = hue; - Tuya.Snapshot[3] = sat; - Tuya.Snapshot[4] = bri; } } } @@ -512,7 +614,7 @@ void LightSerialDuty(uint16_t duty, char *hex_char, uint8_t TuyaIdx) } AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value %d for dpid %d"), duty, dpid); // due to 0 or already set } else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); // + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); } } @@ -564,7 +666,6 @@ void TuyaProcessStatePacket(void) { fnId = TuyaGetFuncId(Tuya.buffer[dpidStart]); AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: fnId=%d is set for dpId=%d"), fnId, Tuya.buffer[dpidStart]); - // if (TuyaFuncIdValid(fnId)) { if (Tuya.buffer[dpidStart + 1] == 1) { // Data Type 1 if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { @@ -590,10 +691,6 @@ void TuyaProcessStatePacket(void) { bool tuya_energy_enabled = (XNRG_32 == TasmotaGlobal.energy_driver); uint16_t packetValue = Tuya.buffer[dpidStart + 6] << 8 | Tuya.buffer[dpidStart + 7]; uint8_t dimIndex; - if ((fnId == TUYA_MCU_FUNC_FAN3) || (fnId == TUYA_MCU_FUNC_FAN4) || - (fnId == TUYA_MCU_FUNC_FAN5) || (fnId == TUYA_MCU_FUNC_FAN6)) { - Tuya.FanState = packetValue; - } if (fnId == TUYA_MCU_FUNC_DIMMER || fnId == TUYA_MCU_FUNC_REPORT1) { dimIndex = 0; } @@ -664,33 +761,62 @@ void TuyaProcessStatePacket(void) { } else if (Tuya.buffer[dpidStart + 1] == 3) { // Data Type 3 const unsigned char *dpData = (unsigned char*)&Tuya.buffer[dpidStart + 4]; - if ((TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0) && dpDataLen == 12) { //Decode the RGB hex and transmit HSBCOLOR command + if ((TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0)) { - //Tuya.ignore_dim = true; - char RgbData[13]; - snprintf_P(RgbData, sizeof(RgbData), PSTR("%.*s"), dpDataLen, dpData); + uint8_t RGBType = Settings.tuya_fnid_map[230].dpid; // Select the type of hex configured + char RgbData[15]; + char RGB[7]; char HSB1[5], HSB2[5], HSB3[5]; - snprintf_P(HSB1, sizeof(HSB1), PSTR("%.4s\n"), &RgbData[0]); - snprintf_P(HSB2, sizeof(HSB2), PSTR("%.4s\n"), &RgbData[4]); - snprintf_P(HSB3, sizeof(HSB3), PSTR("%.4s\n"), &RgbData[8]); - - if ((Tuya.Snapshot[2] != ((int)strtol(HSB1, NULL, 16)) || - Tuya.Snapshot[3] != ((int)strtol(HSB2, NULL, 16)) / 10 || Tuya.Snapshot[4] !=((int)strtol(HSB3, NULL, 16)) / 10)) { + scmnd[0] = '\0'; + snprintf_P(RgbData, sizeof(RgbData), PSTR("%.*s"), dpDataLen, dpData); + if (RGBType <= 1 && dpDataLen == 12) { + snprintf_P(HSB1, sizeof(HSB1), PSTR("%.4s\n"), &RgbData[0]); + snprintf_P(HSB2, sizeof(HSB2), PSTR("%.4s\n"), &RgbData[4]); + snprintf_P(HSB3, sizeof(HSB3), PSTR("%.4s\n"), &RgbData[8]); + if ((Tuya.Snapshot[2] != ((int)strtol(HSB1, NULL, 16)) || + Tuya.Snapshot[3] != ((int)strtol(HSB2, NULL, 16)) / 10 || Tuya.Snapshot[4] !=((int)strtol(HSB3, NULL, 16)) / 10)) { + Tuya.Snapshot[2] = ((int)strtol(HSB1, NULL, 16)); + Tuya.Snapshot[3] = ((int)strtol(HSB2, NULL, 16)) / 10; + Tuya.Snapshot[4] = ((int)strtol(HSB3, NULL, 16)) / 10; snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_HSBCOLOR " %d,%d,%d"), ((int)strtol(HSB1, NULL, 16)), ((int)strtol(HSB2, NULL, 16)) / 10, ((int)strtol(HSB3, NULL, 16)) / 10); - ExecuteCommand(scmnd, SRC_SWITCH); + } + } + if (RGBType > 1 && dpDataLen == 14) { + snprintf_P(RGB, sizeof(RGB), PSTR("%.6s\n"), &RgbData[0]); + if (StrCmpNoCase(RGB, Tuya.RGBColor) != 0) { + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_COLOR " %s"), RGB); + memcpy_P(Tuya.RGBColor, RGB, strlen(RGB)); + } - memcpy_P(Tuya.HSBColor, RgbData, strlen(RgbData)); + } + if (scmnd[0] != '\0') { + ExecuteCommand(scmnd, SRC_SWITCH); } } } else if (Tuya.buffer[dpidStart + 1] == 4) { // Data Type 4 const unsigned char *dpData = (unsigned char*)&Tuya.buffer[dpidStart + 4]; - if (fnId == TUYA_MCU_FUNC_MODESET) { // toggle light type + + if ((fnId == TUYA_MCU_FUNC_MODESET)) { // Toggle light type Tuya.ModeSet = dpData[0]; Tuya.Levels[3] = dpData[0]; } + if ((fnId >= TUYA_MCU_FUNC_ENUM1) && (fnId <= TUYA_MCU_FUNC_ENUM4)) { + // if ((fnId == TUYA_MCU_FUNC_ENUM1) || (fnId == TUYA_MCU_FUNC_ENUM2) || + // (fnId == TUYA_MCU_FUNC_ENUM3) || (fnId == TUYA_MCU_FUNC_ENUM4)) { + for (uint8_t i = 0; i <= 3; i++) { + bool noupdate = false; + if ((TUYA_MCU_FUNC_ENUM1 + i) == fnId) { + if (Tuya.EnumState[i] != dpData[0]) { + Tuya.EnumState[i] = dpData[0]; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_ENUM "%d %d"), i+1, dpData[0]); + ExecuteCommand(scmnd, SRC_SWITCH); + } + } + } + } } dpidStart += dpDataLen + 4; } @@ -912,7 +1038,7 @@ void TuyaSerialInput(void) uint16_t DataVal = 0; uint8_t dpId = 0; uint8_t dpDataType = 0; - char DataStr[13]; + char DataStr[15]; if (len > 0) { ResponseAppend_P(PSTR(",\"CmndData\":\"%s\""), ToHex_P((unsigned char*)&Tuya.buffer[6], len, hex_char, sizeof(hex_char))); @@ -920,7 +1046,6 @@ void TuyaSerialInput(void) //55 AA 03 07 00 0D 01 04 00 01 02 02 02 00 04 00 00 00 1A 40 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 uint8_t dpidStart = 6; - //snprintf_P(DataStr, sizeof(DataStr), PSTR("000000000000")); while (dpidStart + 4 < Tuya.byte_counter) { dpId = Tuya.buffer[dpidStart]; dpDataType = Tuya.buffer[dpidStart + 1]; @@ -969,12 +1094,11 @@ void TuyaSerialInput(void) if (dpId != 0 && Settings.tuyamcu_topic) { // Publish a /STAT Topic ready to use for any home automation system if (!Tuya.SuspendTopic) { - char scommand[10]; - snprintf_P(scommand, sizeof(scommand), PSTR("TuyaSend%d"), dpDataType); - - if (dpDataType != 3 && dpDataType != 5) { Response_P(PSTR("%d,%u"), dpId, DataVal); } - else { Response_P(PSTR("%d,%s"), dpId, DataStr); } - MqttPublishPrefixTopic_P(STAT, (PSTR("%s"), scommand)); + char scommand[13]; + snprintf_P(scommand, sizeof(scommand), PSTR("DpType%uId%u"), dpDataType, dpId); + if (dpDataType != 3 && dpDataType != 5) { Response_P(PSTR("%u"), DataVal); } + else { Response_P(PSTR("%s"), DataStr); } + MqttPublishPrefixTopic_P(STAT, scommand); } }