From cf8cd47126cd051aa834abc1e316168d8f50dd43 Mon Sep 17 00:00:00 2001 From: David Gwynne Date: Mon, 3 Feb 2020 15:02:09 +1100 Subject: [PATCH 1/5] Add a key to the TuyaReceived to help when writing boilerplate rules. The key is in the form CmndDpIdDpType with a value that is the hex encoding of the DpIdData. This allows Rules to be written that target status updates from a specific DpId and of a specific message type. For example, an Anko HEGSM40 fan reports the speed the fan is operating at via STAT message on DpId 4 of type Enum. To publish the speed to MQTT as it's reported from the MCU, I can use the following rule: on TuyaReceived#Cmnd7DpId3DpType4 do Publish stat/%topic%/SPEED %value% endon This appears "on the wire" as: stat/tasmota/SPEED 01 --- tasmota/xdrv_16_tuyamcu.ino | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index da189c568..4fc45e913 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -683,7 +683,9 @@ void TuyaSerialInput(void) uint8_t dpidStart = 6; while (dpidStart + 4 < Tuya.byte_counter) { uint16_t dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; - ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), Tuya.buffer[dpidStart], Tuya.buffer[dpidStart], Tuya.buffer[dpidStart + 1], ToHex_P((unsigned char*)&Tuya.buffer[dpidStart + 4], dpDataLen, hex_char, sizeof(hex_char))); + const char *dpData = ToHex_P((unsigned char*)&Tuya.buffer[dpidStart + 4], dpDataLen, hex_char, sizeof(hex_char)); + ResponseAppend_P(PSTR(",\"Cmnd%dDpId%dDpType%d\":\"%s\""), Tuya.buffer[3], Tuya.buffer[dpidStart], Tuya.buffer[dpidStart + 1], dpData); + ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), Tuya.buffer[dpidStart], Tuya.buffer[dpidStart], Tuya.buffer[dpidStart + 1], dpData); if (TUYA_TYPE_STRING == Tuya.buffer[dpidStart + 1]) { ResponseAppend_P(PSTR(",\"Type3Data\":\"%.*s\""), dpDataLen, (char *)&Tuya.buffer[dpidStart + 4]); } From d651e5c4a21577c9d72ae69dfb3753a36d705113 Mon Sep 17 00:00:00 2001 From: David Gwynne Date: Mon, 3 Feb 2020 21:41:46 +1100 Subject: [PATCH 2/5] print rxed mcu data so it can be printed in a more natural way. basically it tries to use %d to print things when it can instead of hex strings. --- tasmota/xdrv_16_tuyamcu.ino | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index 4fc45e913..c9a5aa6ca 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -682,12 +682,29 @@ void TuyaSerialInput(void) // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 uint8_t dpidStart = 6; while (dpidStart + 4 < Tuya.byte_counter) { + uint8_t dpId = Tuya.buffer[dpidStart]; + uint8_t dpDataType = Tuya.buffer[dpidStart + 1]; uint16_t dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; - const char *dpData = ToHex_P((unsigned char*)&Tuya.buffer[dpidStart + 4], dpDataLen, hex_char, sizeof(hex_char)); - ResponseAppend_P(PSTR(",\"Cmnd%dDpId%dDpType%d\":\"%s\""), Tuya.buffer[3], Tuya.buffer[dpidStart], Tuya.buffer[dpidStart + 1], dpData); - ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), Tuya.buffer[dpidStart], Tuya.buffer[dpidStart], Tuya.buffer[dpidStart + 1], dpData); - if (TUYA_TYPE_STRING == Tuya.buffer[dpidStart + 1]) { - ResponseAppend_P(PSTR(",\"Type3Data\":\"%.*s\""), dpDataLen, (char *)&Tuya.buffer[dpidStart + 4]); + const unsigned char *dpData = (unsigned char*)&Tuya.buffer[dpidStart + 4]; + const char *dpHexData = ToHex_P(dpData, dpDataLen, hex_char, sizeof(hex_char)); + + ResponseAppend_P(PSTR(",\"Cmnd%dDpId%dDpType%d\":"), Tuya.buffer[3], dpId, dpDataType); + if (TUYA_TYPE_BOOL == dpDataType && dpDataLen == 1) { + ResponseAppend_P(PSTR("\"%d\""), dpData[0]); + } else if (TUYA_TYPE_VALUE == dpDataType && dpDataLen == 4) { + uint32_t dpValue = (uint32_t)dpData[0] << 24 | (uint32_t)dpData[1] << 16 | (uint32_t)dpData[2] << 8 | (uint32_t)dpData[3] << 0; + ResponseAppend_P(PSTR("\"%u\""), dpValue); + } else if (TUYA_TYPE_STRING == dpDataType) { + ResponseAppend_P(PSTR("\"%.*s\""), dpDataLen, dpData); + } else if (TUYA_TYPE_ENUM == dpDataType && dpDataLen == 1) { + ResponseAppend_P(PSTR("\"%d\""), dpData[0]); + } else { + ResponseAppend_P(PSTR("\"0x%s\""), dpHexData); + } + + ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), dpId, dpId, dpDataType, dpHexData); + if (TUYA_TYPE_STRING == dpDataType) { + ResponseAppend_P(PSTR(",\"Type3Data\":\"%.*s\""), dpDataLen, dpData); } ResponseAppend_P(PSTR("}")); dpidStart += dpDataLen + 4; From f3c6627ec667d3771b28a88efbb07e13e0c50696 Mon Sep 17 00:00:00 2001 From: David Gwynne Date: Tue, 4 Feb 2020 21:30:30 +1100 Subject: [PATCH 3/5] Tweak the key/value for the type+id so it's only printed for STAT --- tasmota/xdrv_16_tuyamcu.ino | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index c9a5aa6ca..4a49c8ee0 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -688,18 +688,20 @@ void TuyaSerialInput(void) const unsigned char *dpData = (unsigned char*)&Tuya.buffer[dpidStart + 4]; const char *dpHexData = ToHex_P(dpData, dpDataLen, hex_char, sizeof(hex_char)); - ResponseAppend_P(PSTR(",\"Cmnd%dDpId%dDpType%d\":"), Tuya.buffer[3], dpId, dpDataType); - if (TUYA_TYPE_BOOL == dpDataType && dpDataLen == 1) { - ResponseAppend_P(PSTR("\"%d\""), dpData[0]); - } else if (TUYA_TYPE_VALUE == dpDataType && dpDataLen == 4) { - uint32_t dpValue = (uint32_t)dpData[0] << 24 | (uint32_t)dpData[1] << 16 | (uint32_t)dpData[2] << 8 | (uint32_t)dpData[3] << 0; - ResponseAppend_P(PSTR("\"%u\""), dpValue); - } else if (TUYA_TYPE_STRING == dpDataType) { - ResponseAppend_P(PSTR("\"%.*s\""), dpDataLen, dpData); - } else if (TUYA_TYPE_ENUM == dpDataType && dpDataLen == 1) { - ResponseAppend_P(PSTR("\"%d\""), dpData[0]); - } else { - ResponseAppend_P(PSTR("\"0x%s\""), dpHexData); + if (TUYA_CMD_STATE == Tuya.buffer[3]) { + ResponseAppend_P(PSTR(",\"DpType%uId%u\":"), dpDataType, dpId); + if (TUYA_TYPE_BOOL == dpDataType && dpDataLen == 1) { + ResponseAppend_P(PSTR("\"%u\""), dpData[0]); + } else if (TUYA_TYPE_VALUE == dpDataType && dpDataLen == 4) { + uint32_t dpValue = (uint32_t)dpData[0] << 24 | (uint32_t)dpData[1] << 16 | (uint32_t)dpData[2] << 8 | (uint32_t)dpData[3] << 0; + ResponseAppend_P(PSTR("\"%u\""), dpValue); + } else if (TUYA_TYPE_STRING == dpDataType) { + ResponseAppend_P(PSTR("\"%.*s\""), dpDataLen, dpData); + } else if (TUYA_TYPE_ENUM == dpDataType && dpDataLen == 1) { + ResponseAppend_P(PSTR("\"%u\""), dpData[0]); + } else { + ResponseAppend_P(PSTR("\"0x%s\""), dpHexData); + } } ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), dpId, dpId, dpDataType, dpHexData); From 25034c153ae8e777a498f1f1a43b33c02366bd6b Mon Sep 17 00:00:00 2001 From: David Gwynne Date: Sun, 9 Feb 2020 18:44:05 +1100 Subject: [PATCH 4/5] use TuyaSend0 to send a TUYA_CMD_QUERY_STATE command. --- tasmota/xdrv_16_tuyamcu.ino | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index 4a49c8ee0..11b134489 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -114,6 +114,7 @@ void (* const TuyaCommand[])(void) PROGMEM = { TuyaSend dpId,data +TuyaSend0 -> Sends TUYA_CMD_QUERY_STATE TuyaSend1 11,1 -> Sends boolean (Type 1) data 0/1 to dpId 11 (Max data length 1 byte) 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) @@ -124,9 +125,13 @@ TuyaSend4 11,1 -> Sends enum (Type 4) data 0/1/2/3/4/5 to dpId 11 (Max data leng void CmndTuyaSend(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { + if (XdrvMailbox.index > 4) { + return; + } + if (XdrvMailbox.index == 0) { + TuyaRequestState(); + } else { if (XdrvMailbox.data_len > 0) { - char *p; char *data; uint8_t i = 0; @@ -150,8 +155,8 @@ void CmndTuyaSend(void) { TuyaSendEnum(dpId, strtoul(data, nullptr, 0)); } } - ResponseCmndDone(); } + ResponseCmndDone(); } /* From 6e0cd5bd68df595d31e63d744a48432b7327aa53 Mon Sep 17 00:00:00 2001 From: David Gwynne Date: Wed, 19 Feb 2020 18:10:07 +1100 Subject: [PATCH 5/5] print numbers as numbers in json, not strings. --- tasmota/xdrv_16_tuyamcu.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index 11b134489..f250f6409 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -696,14 +696,14 @@ void TuyaSerialInput(void) if (TUYA_CMD_STATE == Tuya.buffer[3]) { ResponseAppend_P(PSTR(",\"DpType%uId%u\":"), dpDataType, dpId); if (TUYA_TYPE_BOOL == dpDataType && dpDataLen == 1) { - ResponseAppend_P(PSTR("\"%u\""), dpData[0]); + ResponseAppend_P(PSTR("%u"), dpData[0]); } else if (TUYA_TYPE_VALUE == dpDataType && dpDataLen == 4) { uint32_t dpValue = (uint32_t)dpData[0] << 24 | (uint32_t)dpData[1] << 16 | (uint32_t)dpData[2] << 8 | (uint32_t)dpData[3] << 0; - ResponseAppend_P(PSTR("\"%u\""), dpValue); + ResponseAppend_P(PSTR("%u"), dpValue); } else if (TUYA_TYPE_STRING == dpDataType) { ResponseAppend_P(PSTR("\"%.*s\""), dpDataLen, dpData); } else if (TUYA_TYPE_ENUM == dpDataType && dpDataLen == 1) { - ResponseAppend_P(PSTR("\"%u\""), dpData[0]); + ResponseAppend_P(PSTR("%u"), dpData[0]); } else { ResponseAppend_P(PSTR("\"0x%s\""), dpHexData); }