openshwprojects / OpenBK7231T_App

Open source firmware (Tasmota/Esphome replacement) for BK7231T, BK7231N, BL2028N, T34, XR809, W800/W801, W600/W601, BL602 and LN882H
https://openbekeniot.github.io/webapp/devicesList.html
1.44k stars 268 forks source link

TuyaMCU Sensor V0 protocol not fully handled #478

Open sven337 opened 1 year ago

sven337 commented 1 year ago

I am trying to liberate a TH01 temperature&humidity battery-powered sensor, similar to the door open sensor (CB3S wifi module controlled by the Tuya MCU).

It seems to use protocol V0. But, driver/drv_tuyaMCU.c doesn't really seem to handle it.

This is what I observe:

Info:TuyaMCU:TUYAMCU received: 55 AA 00 02 00 00 01 
Info:TuyaMCU:TuyaMCU_ProcessIncoming[ver=0]: processing command 2 (MCUconf) with 7 bytes
Info:TuyaMCU:TuyaMCU_ProcessIncoming: TUYA_CMD_MCU_CONF had wrong data lenght?

But, in V0 protocol, this command isn't TUYA_CMD_MCU_CONF but TUYA_V0_CMD_NETWORKSTATUS. I am new to OpenBK7231T so I do not know how to connect the V0 vs. V3 logic, but it seems that this would be needed.

Firmware:

sven337 commented 1 year ago

Command 0x02 above needs to be handled so that the TuyaMCU doesn't get confused, I think (it will reset the module if it doesn't get a connection success message, I work this around by hooking up the RST pin to Vcc).

Another command in my capture is 0x10:

Info:TuyaMCU:TUYAMCU received: 55 AA 00 10 00 02 01 09 1B 
Info:TuyaMCU:TuyaMCU_ProcessIncoming[ver=0]: processing command 16 (Unknown) with 9 bytes
Info:TuyaMCU:TuyaMCU_ProcessIncoming: unhandled type 16

That one seems to be "obtain DP cache command" : https://developer.tuya.com/en/docs/iot/tuyacloudlowpoweruniversalserialaccessprotocol?id=K95afs9h4tjjh#title-17-Obtain%20DP%20cache%20command

I am not sure what to do with that one.

openshwprojects commented 1 year ago

Hey, would you be able to provide us a full capture from original device for analysis?

v0 support is very basic, but we are going to extend it in the future

sven337 commented 1 year ago

Below is what I get on the UART (TuyaMCU -> CB3S only, not the other way around)

00000250  00 00 00 00 55 aa 00 01  00 24 7b 22 70 22 3a 22  |....U....${"p":"|
00000260  6c 66 33 36 79 35 6e 77  62 38 6a 6b 78 77 67 67  |lf36y5nwb8jkxwgg|
00000270  22 2c 22 76 22 3a 22 31  2e 30 2e 30 22 7d 99 55  |","v":"1.0.0"}.U|
00000280  aa 00 02 00 00 01 55 aa  00 08 00 0f 00 01 01 01  |......U.........|
00000290  01 01 01 01 02 00 04 00  00 00 e7 0a 55 aa 00 08  |............U...|
000002a0  00 0f 00 01 01 01 01 01  01 02 02 00 04 00 00 00  |................|
000002b0  39 5d 55 aa 00 08 00 0c  00 03 03 03 03 03 03 03  |9]U.............|

And here's the boot log of CB3S.

Error:CMD:lfs is absent
Info:GEN:PIN_SetupPins pins have been set up.
Info:MAIN:Time 1, idle 496845/s, free 84424, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 3/38
Info:MAIN:Time 2, idle 498650/s, free 84424, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 3/38
Info:MAIN:Time 3, idle 498703/s, free 84424, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 3/38
Info:TuyaMCU:TUYAMCU received: 55 AA 00 01 00 24 7B 22 70 22 3A 22 6C 66 33 36 79 35 6E 77 62 38 6A 6B 78 77 67 67 22 2C 22 76 22 3A 22 31 2E 30 2E 30 22 7D 99 
Info:TuyaMCU:TuyaMCU_ProcessIncoming[ver=0]: processing command 1 (QueryProductInformation) with 43 bytes
Info:TuyaMCU:TuyaMCU_ParseQueryProductInformation: received {"p":"lf36y5nwb8jkxwgg","v":"1.0.0"}
Info:MAIN:Time 4, idle 498658/s, free 84424, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 3/38
Info:MAIN:Time 5, idle 497870/s, free 84424, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 3/38
Info:MAIN:Time 6, idle 478595/s, free 78800, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 3/38
Info:TuyaMCU:TUYAMCU received: 55 AA 00 02 00 00 01 
Info:TuyaMCU:TuyaMCU_ProcessIncoming[ver=0]: processing command 2 (MCUconf) with 7 bytes
**Info:TuyaMCU:TuyaMCU_ProcessIncoming: TUYA_CMD_MCU_CONF had wrong data lenght?**
Info:TuyaMCU:TUYAMCU received: 55 AA 00 08 00 0F 00 01 01 01 01 01 01 01 02 00 04 00 00 00 EE 11 
Info:TuyaMCU:TuyaMCU_ProcessIncoming[ver=0]: processing command 8 (QueryState) with 22 bytes
Info:TuyaMCU:TuyaMCU_V0_ParseRealTimeWithRecordStorage: processing dpId 1, dataType 2-DP_TYPE_VALUE and 4 data bytes
Info:TuyaMCU:TuyaMCU_V0_ParseRealTimeWithRecordStorage: raw data 4 int: 238
Info:GEN:CHANNEL_Set channel 1 has changed to 238 (flags 0)

**Info:MAIN:Channel has changed! Publishing change 1 with 238** 
Info:TuyaMCU:TUYAMCU received: 55 AA 00 08 00 0F 00 01 01 01 01 01 01 02 02 00 04 00 00 00 38 5C 
Info:TuyaMCU:TuyaMCU_ProcessIncoming[ver=0]: processing command 8 (QueryState) with 22 bytes
Info:TuyaMCU:TuyaMCU_V0_ParseRealTimeWithRecordStorage: processing dpId 2, dataType 2-DP_TYPE_VALUE and 4 data bytes
Info:TuyaMCU:TuyaMCU_V0_ParseRealTimeWithRecordStorage: raw data 4 int: 56
Info:GEN:CHANNEL_Set channel 2 has changed to 56 (flags 0)

**Info:MAIN:Channel has changed! Publishing change 2 with 56** 
Info:TuyaMCU:TUYAMCU received: 55 AA 00 08 00 0C 00 03 03 03 03 03 03 03 04 00 01 02 2F 
Info:TuyaMCU:TuyaMCU_ProcessIncoming[ver=0]: processing command 8 (QueryState) with 19 bytes
Info:TuyaMCU:TuyaMCU_V0_ParseRealTimeWithRecordStorage: processing dpId 3, dataType 4-DP_TYPE_ENUM and 1 data bytes
Info:TuyaMCU:TuyaMCU_V0_ParseRealTimeWithRecordStorage: raw data 1 byte: 
Info:GEN:CHANNEL_Set channel 3 has changed to 2 (flags 0)

**Info:MAIN:Channel has changed! Publishing change 3 with 2** 
Info:TuyaMCU:TUYAMCU received: 55 AA 00 10 00 02 01 09 1B 
Info:TuyaMCU:TuyaMCU_ProcessIncoming[ver=0]: processing command 16 (Unknown) with 9 bytes
Info:TuyaMCU:TuyaMCU_ProcessIncoming: unhandled type 16
Info:MAIN:Time 7, idle 482928/s, free 78800, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 3/38
Info:MAIN:Time 8, idle 287684/s, free 78968, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 3/38
Info:MAIN:Time 9, idle 0/s, free 78968, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 3/38
Info:MAIN:Time 10, idle 0/s, free 78968, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 3/38
Info:GEN:dhcp=0 ip=0.0.0.0 gate=0.0.0.0 mask=0.0.0.0 mac=fc:67:1f:46:1a:a7 
Info:GEN:sta: 0, softap: 0, b/g/n
Info:MAIN:wl_status 3
Info:MAIN:Main_OnWiFiStatusChange - WIFI_STA_CONNECTING
Info:MAIN:wl_status 10
Info:MAIN:Main_OnWiFiStatusChange - WIFI_STA_CONNECTED
Info:MAIN:Time 11, idle 160976/s, free 79216, MQTT 0(0), bWifi 1, secondsWithNoPing -1, socks 3/38
Info:MAIN:Boot complete time reached (10 seconds)
Info:CFG:####### Set Boot Complete #######
Info:MAIN:Time 12, idle 465763/s, free 79264, MQTT 0(0), bWifi 1, secondsWithNoPing -1, socks 3/38
Info:MAIN:wl_status 11
Info:MAIN:Main_OnWiFiStatusChange - WIFI_STA_CONNECTED

Note the log says "publishing" but it's not actually publishing anything because at that point 1) wifi is not connected 2) MQTT is not connected

and this does not seem to be an artifact of my test setup.

dpId 1 seems to be temperature in tenths of degrees, dpId 2 humidity, no idea about dpId 3 (battery level?)

sven337 commented 1 year ago

The main blocker for functionality on this module seems to be that OpenBK7231 currently doesn't publish anything on MQTT due to the problem described above - the CB3S will get data from TuyaMCU before being connected to wifi.

Now, TuyaMCU_Sensor_RunFrame is supposed to send g_request_state after 6 seconds, but that seems to be too short for my module - looks like it needs about 15 seconds to get a MQTT connection. Doing it manually through the console (uartSendHex 55aa000200010406) works, but:

Info:TuyaMCU:TUYAMCU received: 55 AA 00 08 00 0F 00 01 01 01 01 01 01 01 02 00 04 00 00 00 DD 00 
Info:TuyaMCU:TuyaMCU_ProcessIncoming[ver=0]: processing command 8 (QueryState) with 22 bytes
Info:TuyaMCU:TuyaMCU_V0_ParseRealTimeWithRecordStorage: processing dpId 1, dataType 2-DP_TYPE_VALUE and 4 data bytes
Info:TuyaMCU:TuyaMCU_V0_ParseRealTimeWithRecordStorage: raw data 4 int: 221
**Info:GEN:No change in channel 1 (still set to 221) - ignoring**

Except... it should publish to MQTT because it was never done before

sven337 commented 1 year ago

After configuring pins as LEDs (no idea what I'm doing but by inspection of the code this is what's needed to make it publish to MQTT), I have something that kind of works, and publishes MQTT data every second for the three channels. This is overkill but at least it works.

It required one patch:

diff --git a/src/mqtt/new_mqtt.c b/src/mqtt/new_mqtt.c
index 1ba644f..fffda13 100644
--- a/src/mqtt/new_mqtt.c
+++ b/src/mqtt/new_mqtt.c
@@ -1207,7 +1207,7 @@ OBK_Publish_Result MQTT_DoItemPublish(int idx)
        // NOTE: negative indexes are not channels - they are special values
        role = CHANNEL_GetRoleForOutputChannel(idx);
        if (role == IOR_Relay || role == IOR_Relay_n || role == IOR_LED || role == IOR_LED_n) {
-               MQTT_ChannelPublish(g_publishItemIndex, OBK_PUBLISH_FLAG_MUTEX_SILENT);
+               return MQTT_ChannelPublish(g_publishItemIndex, OBK_PUBLISH_FLAG_MUTEX_SILENT);
        }

        return OBK_PUBLISH_WAS_NOT_REQUIRED; // didnt publish

Otherwise g_publishItemIndex never gets incremented.

Random notes I have nowhere else to store for now:

openshwprojects commented 1 year ago

Wait wait wait, I see you did find a bug, thanks, and did a great progress with deciphering that device, but I think there one flag that could help you: image "Broadcast self state on MQTT connect" - have you tried that?

Regarding DpID 3 I researched it few months ago and also read that's a battery.... hm.

Your change applied: https://github.com/openshwprojects/OpenBK7231T_App/commit/bfbd27618becb86458b8395db24bf6f5864b9183

_Now, TuyaMCU_Sensor_RunFrame is supposed to send g_requeststate after 6 seconds, but that seems to be too short for my module - looks like it needs about 15 seconds to get a MQTT connection. Doing it manually through the console (uartSendHex 55aa000200010406) works, but:

My assumption was that it DOES NOT have to be on MQTT yet, because the flag "Publish everything on MQTT connect" would publish stuff anyway. What do you think?

EDIT: I can see what might be a problem... you had to configure pins as LEDs because otherwise following block won't publish that channel. It is indeed a bug,I must think about it.

sven337 commented 1 year ago

Regarding DpID 3 I researched it few months ago and also read that's a battery.... hm.

It reports 1 or 2 for me across the entire voltage range. I know for a fact the Smart Life application tries to report battery status (but if I remember correctly it's more of a "low battery yes or no?" than an actual level). So maybe 1 means good and 2 means low, I would need to test that further.

_Now, TuyaMCU_Sensor_RunFrame is supposed to send g_requeststate after 6 seconds, but that seems to be too short for my module - looks like it needs about 15 seconds to get a MQTT connection. Doing it manually through the console (uartSendHex 55aa000200010406) works, but:

Ignore this comment due to the below.

My assumption was that it DOES NOT have to be on MQTT yet, because the flag "Publish everything on MQTT connect" would publish stuff anyway. What do you think?

I assume that would work, but your edit identified the root cause.

EDIT: I can see what might be a problem... you had to configure pins as LEDs because otherwise following block won't publish that channel. It is indeed a bug,I must think about it.

Exactly. It works but felt wrong to me, although I do not know the concepts of OpenBK7231T (what's a "pin", is it a physical pin?) well enough to have an informed opinion.

Note -- the sensor driver will publish MQTT state repeatedly:

nov. 18 09:57:55 obk1F461AA7/1/get 183
nov. 18 09:57:56 obk1F461AA7/2/get 60
nov. 18 09:57:57 obk1F461AA7/3/get 1
nov. 18 09:57:59 obk1F461AA7/1/get 183
nov. 18 09:58:00 obk1F461AA7/2/get 60
nov. 18 09:58:01 obk1F461AA7/3/get 1
nov. 18 09:58:03 obk1F461AA7/1/get 183
nov. 18 09:58:04 obk1F461AA7/2/get 60
nov. 18 09:58:05 obk1F461AA7/3/get 1

When in fact what is needed is one publish + one feedback to TuyaMCU that everything is OK so that it can turn us off again. Here it will stay up for ~90 seconds publishing the same thing over and over again until TuyaMCU forcibly shuts it off. That's not a bug but a feature request.

Sorry this issue is becoming a mess. Do you want seperate issues or do we keep this one as the umbrella "TS01 support" issue?

sven337 commented 1 year ago

When in fact what is needed is one publish + one feedback to TuyaMCU that everything is OK so that it can turn us off again. Here it will stay up for ~90 seconds publishing the same thing over and over again until TuyaMCU forcibly shuts it off. That's not a bug but a feature request.

I tried the patch below, but it doesn't seem that the reply makes TuyaMCU turn us off. Maybe we also need to report network status. That patch does have the advantage of reporting only once instead of starting to publish all the time.

diff --git a/src/driver/drv_tuyaMCU.h b/src/driver/drv_tuyaMCU.h
index 348aacf..08530f7 100644
--- a/src/driver/drv_tuyaMCU.h
+++ b/src/driver/drv_tuyaMCU.h
@@ -5,3 +5,5 @@ void TuyaMCU_RunFrame();
 void TuyaMCU_Send(byte *data, int size);
 void TuyaMCU_OnChannelChanged(int channel,int iVal);
 void TuyaMCU_Send_RawBuffer(byte *data, int len);
+void TuyaMCU_SendCommandWithData(byte cmdType, byte *data, int payload_len);
+
diff --git a/src/driver/drv_tuyaMCUSensor.c b/src/driver/drv_tuyaMCUSensor.c
index 2ef4931..285e3fb 100644
--- a/src/driver/drv_tuyaMCUSensor.c
+++ b/src/driver/drv_tuyaMCUSensor.c
@@ -20,7 +20,9 @@ static byte g_request_state[] =  { 0x55, 0xAA, 0x00, 0x02, 0x00, 0x01, 0x04, 0x0
 void TuyaMCU_Sensor_Init() {
    g_elapsedTime = 0;
 }
+
 void TuyaMCU_Sensor_RunFrame() {
+    static bool started_publishing = false;

    g_elapsedTime++;

@@ -28,11 +30,13 @@ void TuyaMCU_Sensor_RunFrame() {
        TuyaMCU_Send_RawBuffer(g_hello,sizeof(g_hello));
    }
    else if(g_elapsedTime == 6) {
+        addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "TuyaMCU_Sensor_RunFrame: getting state\n");
        TuyaMCU_Send_RawBuffer(g_request_state,sizeof(g_request_state));
    } else if(g_elapsedTime > 10) {
        if(Main_HasMQTTConnected()) {
            g_hadMQTT++;
-           if(g_hadMQTT > 2){
+           if(g_hadMQTT > 2 && !started_publishing){
+                started_publishing = true;
                MQTT_PublishOnlyDeviceChannelsIfPossible();
            }
        } else {
@@ -41,6 +45,14 @@ void TuyaMCU_Sensor_RunFrame() {
    } else if(g_elapsedTime > 50){
        g_elapsedTime = 0;
    }
+
+    if (started_publishing && !g_bPublishAllStatesNow) {
+        // Started to publish and nothing left to publish? Report to TuyaMCU that data has been published
+
+        uint8_t status = 0; // "Reported successfully"
+        addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "TuyaMCU_Sensor_RunFrame: reply to MCU that data has been reported\n");
+        TuyaMCU_SendCommandWithData(0x8 /*TUYA_V0_CMD_RECORDSTATUS*/, &status, 1); 
+    }
 }

diff --git a/src/mqtt/new_mqtt.h b/src/mqtt/new_mqtt.h
index 49012bf..99bccbc 100644
--- a/src/mqtt/new_mqtt.h
+++ b/src/mqtt/new_mqtt.h
@@ -103,4 +103,5 @@ void MQTT_QueuePublishWithCommand(char* topic, char* channel, char* value, int f
 OBK_Publish_Result MQTT_Publish(char* sTopic, char* sChannel, char* value, int flags);
 bool MQTT_IsReady();

+extern int g_bPublishAllStatesNow;
 #endif // __NEW_MQTT_H__
openshwprojects commented 1 year ago

I will add a flag for you: image image

I am not making it a "default" behaviour because in general we are trying to avoid too many publishes at the same time... at least we are trying.

"Note -- the sensor driver will publish MQTT state repeatedly:" image

Pin is a physical pin.

No need for new issue, but if you want to help, you could do a Teardown + Configuration + where to buy post on our forum, follow guide here: https://openbekeniot.github.io/webapp/devicesList.html Post here: https://www.elektroda.com/rtvforum/forum507.html Then we could add this device to supported list (there were some attempts with similar ones but one more teardown + config dump won't hurt). Thanks in advance.

Ok, the question is, were my edits sufficient for your device, or am I still missing something?

EDIT - I haven't seen your changes when I posted this, but we basically did the same. Still, if you want your option to be added, please just submit a pull request. Your change only seems a bit more optimistic than mine, because.... because you don't republish again after a given time.

sven337 commented 1 year ago

I am not making it a "default" behaviour because in general we are trying to avoid too many publishes at the same time... at least we are trying.

Maybe it should be default when tmSensor is in use? I think tmSensor needs it if you don't want to configure pins the way I did.

No need for new issue, but if you want to help, you could do a Teardown + Configuration + where to buy post on our forum, follow guide here: https://openbekeniot.github.io/webapp/devicesList.html Post here: https://www.elektroda.com/rtvforum/forum507.html Then we could add this device to supported list (there were some attempts with similar ones but one more teardown + config dump won't hurt). Thanks in advance.

Will do.

Ok, the question is, were my edits sufficient for your device, or am I still missing something?

EDIT - I haven't seen your changes when I posted this, but we basically did the same. Still, if you want your option to be added, please just submit a pull request. Your change only seems a bit more optimistic than mine, because.... because you don't republish again after a given time.

Yes, your version is better, but it's temporary anyway - the end game should be to report back to TuyaMCU so that it shuts us down ASAP in order to save on battery. I measured about 70mA of power consumption on the CB3S, and currently it is online for about 90 seconds every 180 seconds, that is, 50% of the time. We need to reduce this dramatically if we want decent battery capacity. So the right thing to do is figure out what to send to TuyaMCU so that it shuts us down after 7 seconds as described in their doc: https://airtake-public-data-1254153901.cos.ap-shanghai.myqcloud.com/goat/20200814/3b1354bd9a74469d9de0d20b02d1aca9.png

openshwprojects commented 1 year ago

Ah indeed, I see you also added this block: image the potential problem with that it's setting g_bPublishAllStatesNow does NOT guarantee that all publishes were already received by MQTT server. It just says that "all calls to publish of LWIP MQTT library were done". The LWIP MQTT library may still be doing a TCP send or something.

Maybe we could try to adopt your version but add an extra delay?

Please check and submit a pull request

roburb commented 1 year ago

@sven337

No need for new issue, but if you want to help, you could do a Teardown + Configuration + where to buy post on our forum, follow guide here: https://openbekeniot.github.io/webapp/devicesList.html Post here: https://www.elektroda.com/rtvforum/forum507.html Then we could add this device to supported list (there were some attempts with similar ones but one more teardown + config dump won't hurt). Thanks in advance.

Will do.

Hi sven337 is there anything new about the "tutorial"? I don't know how to start. Thank you

sven337 commented 1 year ago

Do you have the same device? What is your current status, what do you need to know? I have not found time to write the post yet.

roburb commented 1 year ago

Thank you info. Yes I have the same device. I would like to use it MQTT localy only (no tuya cloud).

sven337 commented 1 year ago

Hook up GND, Vcc, RX and TX on the device. Also pull up CEN. This will bypass TuyaMCU and the module should stay active, but TuyaMCU will be powered up so it still will make your life hard on the UART. However, I did manage to flash OpenBK -- after about 15 tries. You can cut the RX and TX traces, in theory that should make things more reliable for flashing, but it's slightly more work afterwards. After that, keep your setup to configure the device. Once you remove your wires, TuyaMCU will forcibly power down the module making it much harder to interact with. Once OpenBK is installed, rely on OTAs not UART flashing. Use the wires to force the module to stay on, because TuyaMCU forcibly cutting power to it (it has a low-side MOSFET for that) will no doubt cause problems.

sven337 commented 1 year ago

Yes, your version is better, but it's temporary anyway - the end game should be to report back to TuyaMCU so that it shuts us down ASAP in order to save on battery. I measured about 70mA of power consumption on the CB3S, and currently it is online for about 90 seconds every 180 seconds, that is, 50% of the time. We need to reduce this dramatically if we want decent battery capacity.

Actually, it seems that my observation was wrong, the device reports temperature much less often. I had 9 days of battery life with 2*AAA NiMH (800mAH Energizer). It's still quite bad.

sven337 commented 1 year ago

I still need to finish reverse engineering this so that TuyaMCU can put the CB3S to sleep, because my average battery life is 9-10 days.

iwl commented 1 year ago

I have some of that TH01 devices, can I flash an Image via WIFI, or do I have to connect them? Seems like still things to improve for practical use. But a nice cheap and simple device for hacking anyway.

sven337 commented 1 year ago

After the first flash you'll be able to use OTAs, the first flash requires some physical hacking that I've described above.

openshwprojects commented 1 year ago

I have a MCU hooked up to PC and I am working on examining the protocol in detail, see information here: https://www.elektroda.com/rtvforum/viewtopic.php?p=20518519#20518519

openshwprojects commented 1 year ago

Latest update should put device to sleep after the publishes are done.

sven337 commented 1 year ago

It did not seem to work out of the box on my TH01 device. I see it draw 75mA constantly until TuyaMCU forcefully shuts down the BK chip after 90 seconds. I need to figure out what's not working.

What I see after the data has been sent by TuyaMCU is this command: Info:TuyaMCU:TUYAMCU received: 55 AA 00 10 00 02 01 09 1B Info:TuyaMCU:TuyaMCU_ProcessIncoming[ver=0]: processing command 16 (Unknown) with 9 bytes Info:TuyaMCU:TuyaMCU_ProcessIncoming: unhandled type 16

This seems to be "Obtain DP cache command" https://developer.tuya.com/en/docs/iot/tuyacloudlowpoweruniversalserialaccessprotocol?id=K95afs9h4tjjh#title-17-Obtain%20DP%20cache%20command

sven337 commented 1 year ago

Replying to obtain DP cache command with a failure:

diff --git a/src/driver/drv_tuyaMCU.c b/src/driver/drv_tuyaMCU.c
index 95f7c11a..ebf53706 100644
--- a/src/driver/drv_tuyaMCU.c
+++ b/src/driver/drv_tuyaMCU.c
@@ -1166,6 +1166,7 @@ void TuyaMCU_ResetWiFi() {
 #define TUYA_V0_CMD_RESETWIFI_AND_SEL_CONF  0x04
 #define TUYA_V0_CMD_REALTIMESTATUS          0x05
 #define TUYA_V0_CMD_RECORDSTATUS            0x08
+#define TUYA_V0_CMD_OBTAINDPCACHE           0x10

 void TuyaMCU_ProcessIncoming(const byte* data, int len) {
        int checkLen;
@@ -1308,6 +1309,15 @@ void TuyaMCU_ProcessIncoming(const byte* data, int len) {
                        TuyaMCU_SendNetworkStatus();
                }
                break;
+    case TUYA_V0_CMD_OBTAINDPCACHE:
+        // This is sent by TH01
+        // Info:TuyaMCU:TUYAMCU received: 55 AA 00 10 00 02 01 09 1B
+            {
+            byte dat = 0x00;
+            TuyaMCU_SendCommandWithData(0x10, &dat, 1);
+            }
+        break;
+
        default:
                addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "TuyaMCU_ProcessIncoming: unhandled type %i", cmd);
                break;

... seems to work! The device now gets powered down by TuyaMCU after about 15 seconds, which should get me 6 times greater battery life!

The problem now is how to do OTAs... maybe we should have OpenBK subscribe to a special MQTT topic (?) to inhibit its replying to TuyaMCU, in order for it not to get powered off.

openshwprojects commented 1 year ago

Wow, i've been planning to look into that 0x10 packet soon, very good job, you saved me a lot of time.

So 0x10 is being sent first by TuyaMCu and then Wifi module replies?

Can you open a pull request?

I was doing OTA by pressing the button for a long time several times and it worked for my door sensors.... but it may not be the best solution

sven337 commented 1 year ago

So 0x10 is being sent first by TuyaMCu and then Wifi module replies?

Yes

Can you open a pull request?

I can if you think it's OK, but what I'm replying to TuyaMCU is "failure" per the documentation. It's asking for some cached DP values that I don't know, and "failure" is sufficient for it to be happy and shut down the module. I assume it would be better to reply the right thing (if we even know it). I would guess one of the values is the reporting interval?

I was doing OTA by pressing the button for a long time several times and it worked for my door sensors.... but it may not be the best solution

Oh, good idea. Better than nothing, I'll try it.

sven337 commented 1 year ago

I'm noting that the module gets powered down sometimes before having finished reporting MQTT status, so my change is not ready to go in as-is. The report DP calls should probably not be acknowledged before MQTT status has been updated.

openshwprojects commented 1 year ago

Isn't DP cache used to set measurement interval? How often device wake up to send data?

sven337 commented 1 year ago

I don't know how to verify what DP cache is used for, but my assumption matches yours. Because the device is turned off by TuyaMCU before MQTT traffic lands, it's hard to tell what the current reporting frequency is. I would say 15 minutes but I am not certain.