How to configure TuyaMCU initial switch state? dpID and script methods for OpenBeken

Some of TuyaMCU switches and relay controllers allow user to set the initial relay state after power on; the initial relay state can be on (contact closed), off (contact open) or memory (retains previous state from before power loss). Usually this setting is configurable via certain dpID, here I will show you how to configure it via OpenBeken. Futhermore, here I will also show a possible OBK work-around for TuyaMCU devices that do not support this feature natively.
For the sake of an example, I will use here HomeMate Wi-Fi + Bluetooth Smart 4 Gang Touch Switch, see link for information:
https://www.elektroda.com/rtvforum/topic3906443.html
Here is a basic OBK config for this device:
startDriver TuyaMCU
setChannelType 1 toggle
setChannelType 2 toggle
setChannelType 3 toggle
setChannelType 4 toggle
setChannelType 13 toggle
setChannelType 7 TextField
setChannelType 8 TextField
setChannelType 9 TextField
setChannelType 10 TextField
// for easier use, map the dpID to the same channel index
// linkTuyaMCUOutputToChannel [dpId] [tuyaVarType] [channelID]
linkTuyaMCUOutputToChannel 1 1 1
linkTuyaMCUOutputToChannel 2 1 2
linkTuyaMCUOutputToChannel 3 1 3
linkTuyaMCUOutputToChannel 4 1 4
linkTuyaMCUOutputToChannel 7 2 7
linkTuyaMCUOutputToChannel 8 2 8
linkTuyaMCUOutputToChannel 9 2 9
linkTuyaMCUOutputToChannel 10 2 10
linkTuyaMCUOutputToChannel 13 1 13
Here are dpID roles:
0 Object { dpName: "Switch 1", dpId: 1 }
1 Object { dpName: "Switch 2", dpId: 2 }
2 Object { dpName: "Switch 3", dpId: 3 }
3 Object { dpName: "Delay-off Schedule", dpId: 19 }
4 Object { dpName: "Switch 4", dpId: 4 }
5 Object { dpName: "Timer 1", dpId: 7 }
6 Object { dpName: "Timer 2", dpId: 8 }
7 Object { dpName: "Test Bit", dpId: 24 }
8 Object { dpName: "Timer 3", dpId: 9 }
9 Object { dpName: "Timer 4", dpId: 10 }
10 Object { dpName: "Master Switch", dpId: 13 }
11 Object { dpName: "Memory Status", dpId: 14 }
The OBK config just maps dpIDs onto OBK channels and sets their types. For more information, see our commands documentation:
https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/commands.md
See also channel types docs:
https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/channelTypes.md
Method 1 - TuyaMCU dpID
First, let's assume that we are lucky and our TuyaMCU device has a dpID setting for initial power on state. In case of HomeMate Wi-Fi + Bluetooth Smart 4 Gang Touch Switch we have:
11 Object { dpName: "Memory Status", dpId: 14 }
If you don't know if your device has such dpID, you can try capturing original Tuya firmware communication with the MCU via UART and toggling the memory setting in Tuya app (if present), you can use our TuyaMCU analyzer for that:
https://github.com/openshwprojects/TuyaMCUAnalyzer
If you have already flashed OBK and don't have Tuya firmware backup, you can also try using OBK tuyaMcu_sendQueryState command to request the full device dpID state and look for the memory dpID there. Here is a sample result (trimmed other dpIDs) from the HomeMate Wi-Fi + Bluetooth Smart 4 Gang Touch Switch:
Info:TuyaMCU:TUYAMCU received: 55 AA 03 07 00 05 0E 04 00 01 02 23
Info:TuyaMCU:TuyaMCU_ProcessIncoming[ver=3]: processing command 7 (State) with 12 bytes
Info:TuyaMCU:TuyaMCU_ParseStateMessage: processing dpId 14, dataType 4-DP_TYPE_ENUM and 1 data bytes
Info:TuyaMCU:TuyaMCU_ParseStateMessage: raw data 1 byte:
Info:MAIN:Time 113, idle 190098/s, free 67840, MQTT 1(1), bWifi 1, secondsWithNoPing 1, socks 2/38
Info:TuyaMCU:TUYAMCU received: 55 AA 03 00 00 01 01 04
In case of this particular TuyaMCU device, dpID responsible for memory status is dpID 14, the type of variable is enum.
The following enum can have three values:
- 0, means "initial state is always off"
- 1, means "initial state is always on",
- 2, means "remember last state"
To set it from OpenBeken, you can use the following command:
// tuyaMcu_sendState [dpID] [VarType] [Value]
tuyaMcu_sendState 14 4 1
Here the dpID is 14, type is 4 (TuyaMCU enum) and value is 1. Value can be 0, 1 or 2.
Of course, TuyaMCU driver should be run first, device should be already configured. Futhermore, you may need to disable MQTT for the time of the testing because MQTT/HA may overwrite TuyaMCU state if not configured correctly.
If you want to enable memory of relays status, use:
// tuyaMcu_sendState [dpID] [VarType] [Value]
tuyaMcu_sendState 14 4 2
This is of course a very basic approach. You can also put that setting on GUI.
Here is a full autoexec.bat with memory setting mapped to GUI:
startDriver TuyaMCU
setChannelType 1 toggle
setChannelType 2 toggle
setChannelType 3 toggle
setChannelType 4 toggle
setChannelType 7 TextField
setChannelType 8 TextField
setChannelType 9 TextField
setChannelType 10 TextField
setChannelType 14 OffOnRemember
linkTuyaMCUOutputToChannel 1 1 1
linkTuyaMCUOutputToChannel 2 1 2
linkTuyaMCUOutputToChannel 3 1 3
linkTuyaMCUOutputToChannel 4 1 4
linkTuyaMCUOutputToChannel 7 2 7
linkTuyaMCUOutputToChannel 8 2 8
linkTuyaMCUOutputToChannel 9 2 9
linkTuyaMCUOutputToChannel 10 2 10
linkTuyaMCUOutputToChannel 14 4 14
The most important things happen here:
linkTuyaMCUOutputToChannel 14 4 14
setChannelType 14 OffOnRemember
This maps dpID 14 of type enum (4) to channel 14 (so it's easier to remember), and also it sets the type of channel 14 to OffOnRemember so the correct widget is shown on OBK gui.
Here is the result in OBK:

Method 2 - Manual OBK state save
In case of non-TuyaMCU devices, remembering the previous state is very easy in OpenBeken. You can just do go to Config->Startup and set the value for each channel there.
For TuyaMCU, however, you might want to choose the manual approach. Here is the full autoexec.bat:
startDriver TuyaMCU
setChannelType 1 toggle
setChannelType 2 toggle
setChannelType 3 toggle
setChannelType 4 toggle
setChannelType 7 TextField
setChannelType 8 TextField
setChannelType 9 TextField
setChannelType 10 TextField
setChannelType 14 TextField
linkTuyaMCUOutputToChannel 1 1 1
linkTuyaMCUOutputToChannel 2 1 2
linkTuyaMCUOutputToChannel 3 1 3
linkTuyaMCUOutputToChannel 4 1 4
linkTuyaMCUOutputToChannel 7 2 7
linkTuyaMCUOutputToChannel 8 2 8
linkTuyaMCUOutputToChannel 9 2 9
linkTuyaMCUOutputToChannel 10 2 10
linkTuyaMCUOutputToChannel 14 4 14
delay_s 1
echo Restoring states: $CH201 $CH202 $CH203 $CH204
setChannel 1 $CH201
delay_s 0.1
setChannel 2 $CH202
delay_s 0.1
setChannel 3 $CH203
delay_s 0.1
setChannel 4 $CH204
// when channel 1 changes, save it to flash channel 201
addEventHandler OnChannelChange 1 setChannel 201 $CH1
// when channel 2 changes, save it to flash channel 202
addEventHandler OnChannelChange 2 setChannel 202 $CH2
// when channel 3 changes, save it to flash channel 202
addEventHandler OnChannelChange 3 setChannel 203 $CH3
// when channel 4 changes, save it to flash channel 204
addEventHandler OnChannelChange 4 setChannel 204 $CH4
This is the extended version of autoexec.bat from before.
Let's analyze the additions:
delay_s 1
echo Restoring states: $CH201 $CH202 $CH203 $CH204
In the code above we print to console the values of flash memory channels, the flash memory channels are starting from $CH200, when you write to this channel, it's saved in flash memory. Echo prints formatted string to console.
setChannel 1 $CH201
delay_s 0.1
setChannel 2 $CH202
delay_s 0.1
setChannel 3 $CH203
delay_s 0.1
setChannel 4 $CH204
In the code above we set channels 1, 2, 3 and 4 (mapped to TuyaMCU) to saved values from flash, every time with delay, to avoid overloading the MCU.
// when channel 1 changes, save it to flash channel 201
addEventHandler OnChannelChange 1 setChannel 201 $CH1
// when channel 2 changes, save it to flash channel 202
addEventHandler OnChannelChange 2 setChannel 202 $CH2
// when channel 3 changes, save it to flash channel 202
addEventHandler OnChannelChange 3 setChannel 203 $CH3
// when channel 4 changes, save it to flash channel 204
addEventHandler OnChannelChange 4 setChannel 204 $CH4
And finally, in the code above, we set the channel change callbacks to save the value in flash every time that the channel changes.
What if I want to set the initial state to constant 1 instead of 'last remembered'?
The previous paragraph covered remembering last state, if you want just to set it to fixed, let's say, 1, you can do:
setChannel 1 1
delay_s 0.1
setChannel 2 1
delay_s 0.1
setChannel 3 1
delay_s 0.1
setChannel 4 1
Summary
There are two ways to setup remembering the last relay state on most TuyaMCU devices - it can be done via Tuya dpID, the same way it works with Tuya firmware, or it can be done manually in OBK.
Some TuyaMCU devices might don't have a 'memory' dpID, or the following dpID may not be known, in such scenario you can just script the OBK to remember the given channel state on change and restore it on reboot. It will also work good and furthermore there is no need to worry about flash wear, as we have a special flash write optimization system where a flash erase is used only once per many write cycles. Let me know which solution you've chosen, I will try to help if any problem arise.
Comments
thanks for this detailed document & instructions. this helped for two devices which had TuyaMCU [Read more]
Thank you very much. This example helped me understand some other doubts I had regarding my project. I will start implementing and testing. Regarding the issue of recording in flash memory, even... [Read more]