TONGOU Tuya Smart WiFi Energy Meter - Teardown


Bought this tiny-shiny power metering module on Aliexpress. What we have inside:
Module: CB2S (BK7231N) - WiFi
TuyaMCU: STC 8H3K64S2
Sensor: BL0942 - power metering
Communication between all parts done using 2 UARTs.
Assembly contains 2 boards and current metering coil bulit into the plastic case. Smaller board is WiFi + TuyaMCU, bigger - power metering sensor with ac/dc converter:





Pinout is classic for "WiFi - TuyaMCU - Sensor" architecture:
Futher invstigation shed light on used bandwidth in stock firmware:
1. UART Module -> TuyaMCU: 115200
2. UART TuyaMCU -> Sensor: 38400
When you disconnect two boards, and power on WiFi + TuyaMCU stock firmware sometimes pauses for a while and after reset via EN0 loops itself, here is sample of UART communication:
Module:
MCU:
Also example of BL0942 UART communication:
Investigation on Tuya Dev portal gave me next list of dpIDs:
And I compiled it into autoexec.bat. It is work in progress, in terms of channel types. so expect few changes later if I came up with better typing:
But the issue with such a long autoexec.bat is memory, so unless I drop half of it, I receive Error:MAIN:Low heap warning! in logs.
Speaking about it, I receive it even with smaller set of channels. Seems like it is related to number of sockets created. My investigation so far gave me next understanding - minimum is 2 sockets (HTTP recv/send? or MQTT?), then DGR adds 2 more (can it be disabled? is it way to go?), then from time to time 5th one created (ping?). If I span NTP driver and it's time sync process conincides with creation of 5th socket, we will have 6 sockets and total lack of free memory results in reboot.
So, watchout for this. Not sure what can be done here, but any help will be appreciated. Example of "normal" log when you balance on the edge, without NTP:
All experiments were done using firmware version 1.18.279 for BK7231N.
AI: What exactly do you want help with here - decoding BL0942 frames, validating TuyaMCU dpIds/channel mapping, or solving the low heap / reboot issue?
Looking into low heap / reboot issue again, if possible.
AI: Which exact firmware/project build are you running on the CB2S (for example OpenBeken version/commit, build target, and any extra features enabled such as MQTT/HTTP/NTP/HA discovery)?
1.18.279 for BK7231N
Bought this tiny-shiny power metering module on Aliexpress. What we have inside:
Module: CB2S (BK7231N) - WiFi
TuyaMCU: STC 8H3K64S2
Sensor: BL0942 - power metering
Communication between all parts done using 2 UARTs.
Assembly contains 2 boards and current metering coil bulit into the plastic case. Smaller board is WiFi + TuyaMCU, bigger - power metering sensor with ac/dc converter:
Pinout is classic for "WiFi - TuyaMCU - Sensor" architecture:
Futher invstigation shed light on used bandwidth in stock firmware:
1. UART Module -> TuyaMCU: 115200
2. UART TuyaMCU -> Sensor: 38400
When you disconnect two boards, and power on WiFi + TuyaMCU stock firmware sometimes pauses for a while and after reset via EN0 loops itself, here is sample of UART communication:
Module:
55 AA 00 00 00 00 FF - Heartbeat (HB)
55 AA 00 00 00 00 FF - HB
55 AA 00 00 00 00 FF - HB
55 AA 00 00 00 00 FF - HB (MCU responded)
55 AA 00 01 00 00 00 - ask product info
55 AA 00 02 00 00 01 - ask working mode
55 AA 00 03 00 01 02 05 - notify Net status "The module searches for network"
55 AA 00 03 00 01 03 06 - notify Net status "The module is registered with the network but not connected to the network"
55 AA 00 08 00 00 07 - ask sensor info (statuses from dpIds)
55 AA 00 03 00 01 04 07 - notify Net status " The module is connected to the network and gets an IP address"
55 AA 00 08 00 00 07 - ask sensor info (statuses from dpIds)
55 AA 00 00 00 00 FF - HB
55 AA 00 00 00 00 FF - HB
55 AA 00 00 00 00 FF - HB
55 AA 00 00 00 00 FF - HB
MCU:
00 - pause
55 AA 03 00 00 01 00 03 - HB response
55 AA 03 01 00 2A 7B 22 ......................................................................... 0F - product info
55 AA 03 02 00 00 04 - response working mode - module works with the MCU to process network events
55 AA 03 07 00 05 6E 04 00 01 0A 8B - dpId 6E (110) status, type Enum, len 0001, value 0A (10) = Under_Voltage_Alarm
55 AA 03 00 00 01 00 03 - HB response
55 AA 03 01 00 2A 7B 22 ......................................................................... 0F - product info
55 AA 03 02 00 00 04 - response working mode
55 AA 03 07 00 05 6E 04 00 01 0A 8B - dpId 6E (110) status
55 AA 03 00 00 01 00 03 - HB reponse
55 AA 03 01 00 2A 7B 22 ......................................................................... 0F - product info
55 AA 03 02 00 00 04 - response working mode
55 AA 03 07 00 05 6E 04 00 01 0A 8B - dpId 6E (110) status
55 AA 03 00 00 01 00 03 - HB response
55 AA 03 01 00 2A 7B 22 ......................................................................... 0F - product info
55 AA 03 07 00 05 6E 04 00 01 0A 8B - dpId 6E (110) status
55 AA 03 02 00 00 04 - response working mode
55 AA 03 00 00 01 00 03 - HB response
55 AA 03 01 00 2A 7B 22 ......................................................................... 0F - product info
55 AA 03 07 00 05 6E 04 00 01 0A 8B - dpId 6E (110) status
55 AA 03 02 00 00 04 - response working mode
....... looping the same
Also example of BL0942 UART communication:
55 00 00 00 87 07 00 12 09 00 00 00 00 00 00 00 20 4E 00 02 03 00 36
55 00 00 00 87 07 00 DE 07 00 00 00 00 00 00 00 20 4E 00 02 03 00 6C
55 00 00 00 87 07 00 F7 07 00 00 00 00 00 00 00 20 4E 00 02 03 00 53
55 00 00 00 87 07 00 34 0A 00 00 00 00 00 00 00 20 4E 00 02 03 00 13
55 00 00 00 87 07 00 9F 09 00 00 00 00 00 00 00 20 4E 00 02 03 00 A9
55 00 00 00 2B 07 00 35 09 00 00 00 00 00 00 00 20 4E 00 02 03 00 6F
55 00 00 00 2B 07 00 B8 0B 00 00 00 00 00 00 00 20 4E 00 02 03 00 EA
55 00 00 00 2B 07 00 65 0A 00 00 00 00 00 00 00 20 4E 00 02 03 00 3E
55 00 00 00 2B 07 00 F8 03 00 00 00 00 00 00 00 20 4E 00 02 03 00 B2
55 00 00 00 2B 07 00 3E 05 00 00 00 00 00 00 00 20 4E 00 02 03 00 6A
55 00 00 00 2B 07 00 81 05 00 00 00 00 00 00 00 20 4E 00 02 03 00 27
55 00 00 00 2B 07 00 CE 03 00 00 00 00 00 00 00 20 4E 00 02 03 00 DC
55 00 00 00 2B 07 00 3C 05 00 00 00 00 00 00 00 20 4E 00 02 03 00 6C
55 00 00 00 2B 07 00 16 06 00 00 00 00 00 00 00 20 4E 00 02 03 00 91
55 00 00 00 2B 07 00 B2 06 00 00 00 00 00 00 00 20 4E 00 02 03 00 F5
55 00 00 00 2B 07 00 D4 0C 00 00 00 00 00 00 00 20 4E 00 02 03 00 CD
Investigation on Tuya Dev portal gave me next list of dpIDs:
"result": [
{ "dpId": 1, "dpName": "Total forward energy" },
{ "dpId": 131, "dpName": "CPU Real-time Temp" },
{ "dpId": 6, "dpName": "Phase A" },
{ "dpId": 11, "dpName": "Prepayment Switch" },
{ "dpId": 12, "dpName": "Clear Remaining Electricity" },
{ "dpId": 13, "dpName": "Remaining Electricity" },
{ "dpId": 14, "dpName": "Electricity Charge" },
{ "dpId": 32, "dpName": "Grid supply frequency" },
{ "dpId": 34, "dpName": "Factory Reset" },
{ "dpId": 101, "dpName": "Eletricity Shortage Setting" },
{ "dpId": 102, "dpName": "Over-voltage Setting" },
{ "dpId": 103, "dpName": "Under-voltage Setting" },
{ "dpId": 104, "dpName": "Over-current Setting" },
{ "dpId": 105, "dpName": "Over-power Setting" },
{ "dpId": 107, "dpName": "Temperature Setting" },
{ "dpId": 109, "dpName": "Online state" },
{ "dpId": 110, "dpName": "Event" },
{ "dpId": 113, "dpName": "Restore Default Switch" },
{ "dpId": 50, "dpName": "Overall Power Factor" },
{ "dpId": 114, "dpName": "Current Threshold" },
{ "dpId": 115, "dpName": "Over-voltage Threshold" },
{ "dpId": 116, "dpName": "Under-voltage Threshold" },
{ "dpId": 118, "dpName": "Temperature Threshold" },
{ "dpId": 119, "dpName": "Over-power Threshold" },
{ "dpId": 120, "dpName": "Electricity Shortage Threshold" },
{ "dpId": 125, "dpName": "Forward Electricity" }
]
And I compiled it into autoexec.bat. It is work in progress, in terms of channel types. so expect few changes later if I came up with better typing:
backlog startDriver TuyaMCU; tuyaMcu_setBaudRate 115200; waitFor MQTTState 1
#tuyaMcu_defWiFiState 4
setChannelLabel 1 "Total forward energy"
setChannelType 1 Power
setChannelLabel 2 "CPU Real-time Temp"
setChannelType 2 Temperature_div10
setChannelLabel 3 "Phase A"
setChannelType 3 ReadOnly
setChannelLabel 4 "Prepayment Switch"
setChannelType 4 Toggle
setChannelLabel 5 "Clear Remaining Electricity"
setChannelType 5 Toggle
setChannelLabel 6 "Remaining Electricity"
setChannelType 6 ReadOnly
setChannelLabel 7 "Electricity Charge"
setChannelType 7 Default
setChannelLabel 8 "Grid supply frequency"
setChannelType 8 Frequency_div100
setChannelLabel 9 "Factory Reset"
setChannelType 9 Toggle
setChannelLabel 10 "Eletricity Shortage Setting"
setChannelType 10 Enum
setChannelEnum 10 0:Closed 1:Alarm
setChannelLabel 11 "Over-voltage Setting"
setChannelType 11 Enum
setChannelEnum 11 0:Closed 1:Alarm
setChannelLabel 12 "Under-voltage Setting"
setChannelType 12 Enum
setChannelEnum 12 0:Closed 1:Alarm
setChannelLabel 13 "Over-current Setting"
setChannelType 13 Enum
setChannelEnum 13 0:Closed 1:Alarm
setChannelLabel 14 "Over-power Setting"
setChannelType 14 Enum
setChannelEnum 14 0:Closed 1:Alarm
setChannelLabel 15 "Temperature Setting"
setChannelType 15 Enum
setChannelEnum 15 0:Closed 1:Alarm
setChannelLabel 16 "Online state"
setChannelType 16 Enum
setChannelEnum 16 0:Online 1:Offline
setChannelLabel 17 "Event"
setChannelType 17 Enum
setChannelEnum 17 0:Normal 1:Over_Current_Trip 2:Over_Power_Trip 3:High_Temp_Trip 4:Over_Voltage_Trip 5:Under_Voltage_Trip 6:Over_Current_Alarm 7:Over_Power_Alarm 8:High_Temp_Alarm 9:Over_Voltage_Alarm 10:Under_Voltage_Alarm 11:Remote_ON 12:Remote_OFF 13:Manual_ON 14:Manual_OFF 15:Leakage_Trip 16:Leakage_Alarm 17:Restore_Default 18:Automatic_Closing 19:Electricity_Shortage 20:Electricity_Shortage_Alarm 21:Timing_switch_ON 22:Timing_switch_OFF 23:Electricity_Reset
setChannelLabel 18 "Restore Default Switch"
setChannelType 18 Toggle
setChannelLabel 19 "Overall Power Factor"
setChannelType 19 Power
setChannelLabel 20 "Current Threshold"
setChannelType 20 Current
setChannelLabel 21 "Over-voltage Threshold"
setChannelType 21 Voltage
setChannelLabel 22 "Under-voltage Threshold"
setChannelType 22 Voltage
setChannelLabel 23 "Temperature Threshold"
setChannelType 23 Temperature_div10
setChannelLabel 24 "Over-power Threshold"
setChannelType 24 Power
setChannelLabel 25 "Electricity Shortage Threshold"
setChannelType 25 Power
setChannelLabel 26 "Forward Electricity"
setChannelType 26 Power
linkTuyaMCUOutputToChannel 1 val 1
linkTuyaMCUOutputToChannel 131 val 2
linkTuyaMCUOutputToChannel 6 raw 3
linkTuyaMCUOutputToChannel 11 bool 4
linkTuyaMCUOutputToChannel 12 bool 5
linkTuyaMCUOutputToChannel 13 val 6
linkTuyaMCUOutputToChannel 14 val 7
linkTuyaMCUOutputToChannel 32 val 8
linkTuyaMCUOutputToChannel 34 bool 9
linkTuyaMCUOutputToChannel 101 enum 10
linkTuyaMCUOutputToChannel 102 enum 11
linkTuyaMCUOutputToChannel 103 enum 12
linkTuyaMCUOutputToChannel 104 enum 13
linkTuyaMCUOutputToChannel 105 enum 14
linkTuyaMCUOutputToChannel 107 enum 15
linkTuyaMCUOutputToChannel 109 enum 16
linkTuyaMCUOutputToChannel 110 enum 17
linkTuyaMCUOutputToChannel 113 bool 18
linkTuyaMCUOutputToChannel 50 val 19
linkTuyaMCUOutputToChannel 114 val 20
linkTuyaMCUOutputToChannel 115 val 21
linkTuyaMCUOutputToChannel 116 val 22
linkTuyaMCUOutputToChannel 118 val 23
linkTuyaMCUOutputToChannel 119 val 24
linkTuyaMCUOutputToChannel 120 val 25
linkTuyaMCUOutputToChannel 125 val 26
But the issue with such a long autoexec.bat is memory, so unless I drop half of it, I receive Error:MAIN:Low heap warning! in logs.
Speaking about it, I receive it even with smaller set of channels. Seems like it is related to number of sockets created. My investigation so far gave me next understanding - minimum is 2 sockets (HTTP recv/send? or MQTT?), then DGR adds 2 more (can it be disabled? is it way to go?), then from time to time 5th one created (ping?). If I span NTP driver and it's time sync process conincides with creation of 5th socket, we will have 6 sockets and total lack of free memory results in reboot.
So, watchout for this. Not sure what can be done here, but any help will be appreciated. Example of "normal" log when you balance on the edge, without NTP:
Info:MAIN:Main_Init_Before_Delay
Warn:CFG:CFG_InitAndLoad: Correct config has been loaded with 59 changes count.
Info:NTP:CLOCK driver initialized.
Error:CMD:no file early.bat err -2
Info:GEN:PIN_SetupPins pins have been set up.
Info:MAIN:Main_Init_Before_Delay done
Info:MAIN:Main_Init_Delay
Info:MAIN:Main_Init_Delay done
Info:MAIN:Main_Init_After_Delay
Info:MAIN:Registered for wifi changes
Info:MAIN:Connecting to SSID [xxx]
Info:GEN:We have fast connection data, connecting...
Info:MAIN:Using SSID [xxx]
Info:MAIN:Using Pass [xxx]
Error:HTTP:Created HTTP SV thread with (stack=2048)
Info:MQTT:MQTT_RegisterCallback called for bT ...
...
Info:CMD:CMD_StartScript: started @startup at the beginning
Info:CMD:CMD_StartScript: started autoexec.bat at the beginning
Info:MAIN:Main_Init_After_Delay done
Info:MAIN:Main_OnWiFiStatusChange - WIFI_STA_CONNECTING - 1
Info:MAIN:Time 2, idle 238846/s, free 70208, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 2/38
Info:MAIN:HA discovery is scheduled, but MQTT connection is not present yet
Info:MAIN:Main_OnWiFiStatusChange - WIFI_STA_DISCONNECTED - 2
Info:MAIN:Time 3, idle 171848/s, free 72248, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 2/38
Info:MAIN:HA discovery is scheduled, but MQTT connection is not present yet
Info:MAIN:Time 4, idle 173481/s, free 72248, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 2/38
Info:MAIN:HA discovery is scheduled, but MQTT connection is not present yet
Info:MAIN:Time 5, idle 173914/s, free 72248, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 2/38
Info:MAIN:HA discovery is scheduled, but MQTT connection is not present yet
Info:MAIN:Time 6, idle 172987/s, free 72248, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 2/38
Info:MAIN:Boot complete time reached (5 seconds)
Info:MAIN:HA discovery is scheduled, but MQTT connection is not present yet
Info:MAIN:Time 7, idle 167686/s, free 72248, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 2/38
Info:MAIN:HA discovery is scheduled, but MQTT connection is not present yet
Info:MAIN:Registered for wifi changes
Info:MAIN:Connecting to SSID [...]
Info:GEN:We have fast connection data, connecting...
Info:MAIN:Main_OnWiFiStatusChange - WIFI_STA_AUTH_FAILED - 3
Info:MAIN:Time 8, idle 164627/s, free 72408, MQTT 0(0), bWifi 0, secondsWithNoPing -1, socks 2/38
Info:MAIN:HA discovery is scheduled, but MQTT connection is not present yet
Info:MAIN:Main_OnWiFiStatusChange - WIFI_STA_CONNECTING - 1
Info:MAIN:Main_OnWiFiStatusChange - WIFI_STA_DISCONNECTED - 2
Info:MAIN:Main_OnWiFiStatusChange - WIFI_STA_DISCONNECTED - 2
Info:MAIN:Main_OnWiFiStatusChange - WIFI_STA_CONNECTED - 4
Info:MQTT:mqtt_userName xxx
mqtt_pass ********
mqtt_clientID home/power/meter/pm1
mqtt_host xxx.xxx.xxx.xxx
Info:MAIN:Time 9, idle 153094/s, free 63376, MQTT 0(1), bWifi 1, secondsWithNoPing -1, socks 3/38
Info:MAIN:HA discovery is scheduled, but MQTT connection is not present yet
Info:MQTT:mqtt_connection_cb: Successfully connected
...
Info:MAIN:Will do request HA discovery now.
Info:HTTP:HASS counts: 0 rels, 0 pwms, 0 inps, 0 excluded
....
Info:MAIN:Time 12, idle 164767/s, free 28824, MQTT 1(1), bWifi 1, secondsWithNoPing -1, socks 2/38
Info:MAIN:Starting DGR.
Info:DGR:DRV_DGR_CreateSocket_Receive: Socket created, waiting for packets
Info:DGR:DRV_DGR_CreateSocket_Send: socket created
Info:MAIN:Started DGR.
Info:MAIN:Time 13, idle 174442/s, free 27992, MQTT 1(1), bWifi 1, secondsWithNoPing -1, socks 4/38
....
Info:GEN:sta:rssi=-36,ssid=xxx,bssid=d6:01:c3:84:9a:cc,channel=1,cipher_type:CCMP
Info:MAIN:Time 511, idle 176403/s, free 27984, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 5/38
Error:MAIN:Low heap warning!
Info:MAIN:Time 512, idle 174322/s, free 19592, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 5/38
Info:MAIN:Time 513, idle 171779/s, free 28200, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 4/38
Error:MAIN:Low heap warning!
Info:MAIN:Time 514, idle 170056/s, free 19592, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 5/38
Info:MAIN:Time 515, idle 171680/s, free 28200, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 4/38
Error:MAIN:Low heap warning!
Info:MAIN:Time 516, idle 173396/s, free 19592, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 5/38
Info:MAIN:Time 517, idle 173121/s, free 28200, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 4/38
Error:MAIN:Low heap warning!
Info:MAIN:Time 518, idle 174095/s, free 19376, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 6/38
Info:MAIN:Time 519, idle 172901/s, free 28200, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 4/38
Error:MAIN:Low heap warning!
Info:MAIN:Time 520, idle 170614/s, free 19592, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 5/38
Info:GEN:dhcp=0 ip=xxx.xxx.xxx.xxx gate=xxx.xxx.xxx.xxx mask=xxx.xxx.xxx.xxx mac=xx:xx:xx:xx:xx:xx
Info:GEN:sta: 1, softap: 0, b/g/n
Info:GEN:sta:rssi=-36,ssid=xxx,bssid=d6:01:c3:84:9a:cc,channel=1,cipher_type:CCMP
Info:MAIN:Time 521, idle 168332/s, free 28200, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 4/38
Error:MAIN:Low heap warning!
Info:MAIN:Time 522, idle 173586/s, free 19592, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 5/38
Info:MAIN:Time 523, idle 173210/s, free 28200, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 4/38
Error:MAIN:Low heap warning!
Info:MAIN:Time 524, idle 173319/s, free 19592, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 5/38
Info:MAIN:Time 525, idle 171670/s, free 27984, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 5/38
Info:MAIN:Time 526, idle 174442/s, free 27984, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 5/38
Info:MAIN:Time 527, idle 168358/s, free 28200, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 4/38
Error:MAIN:Low heap warning!
Info:MAIN:Time 528, idle 176214/s, free 19592, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 5/38
Info:MAIN:Time 529, idle 173711/s, free 28200, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 4/38
Error:MAIN:Low heap warning!
Info:MAIN:Time 530, idle 173255/s, free 19592, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 5/38
Info:GEN:dhcp=0 ip=xxx.xxx.xxx.xxx gate=xxx.xxx.xxx.xxx mask=xxx.xxx.xxx.xxx mac=xx:xx:xx:xx:xx:xx
Info:GEN:sta: 1, softap: 0, b/g/n
Info:GEN:sta:rssi=-37,ssid=xxx,bssid=xx:xx:xx:xx:xx:xx,channel=1,cipher_type:CCMP
Info:MAIN:Time 531, idle 171341/s, free 28200, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 4/38
Error:MAIN:Low heap warning!
Info:MAIN:Time 532, idle 173088/s, free 19376, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 6/38
Info:MAIN:Time 533, idle 170561/s, free 28200, MQTT 1(2), bWifi 1, secondsWithNoPing -1, socks 4/38
All experiments were done using firmware version 1.18.279 for BK7231N.
AI: What exactly do you want help with here - decoding BL0942 frames, validating TuyaMCU dpIds/channel mapping, or solving the low heap / reboot issue?
Looking into low heap / reboot issue again, if possible.
AI: Which exact firmware/project build are you running on the CB2S (for example OpenBeken version/commit, build target, and any extra features enabled such as MQTT/HTTP/NTP/HA discovery)?
1.18.279 for BK7231N