ttuyamcu noread flag (#1820)

* noread

* fx

* ping pong mode for addChannel

* Update new_pins.c

* test
This commit is contained in:
openshwprojects
2025-10-09 15:59:44 +02:00
committed by GitHub
parent 883e85e4cc
commit c208c19f3e
4 changed files with 169 additions and 53 deletions

View File

@@ -67,7 +67,8 @@ static byte g_tuyaMCUConfirmationsToSend_0x08 = 0;
static byte g_tuyaMCUConfirmationsToSend_0x05 = 0;
static byte g_resetWiFiEvents = 0;
#define OBKTM_FLAG_DPCACHE 1
#define OBKTM_FLAG_NOREAD 2
//=============================================================================
//dp data point type
@@ -161,7 +162,7 @@ typedef struct tuyaMCUMapping_s {
// data point type (one of the DP_TYPE_xxx defines)
byte dpType;
// true if it's supposed to be sent in dp cache
byte bDPCache;
byte obkFlags;
// could be renamed to flags later?
byte inv;
// target channel
@@ -336,7 +337,7 @@ tuyaMCUMapping_t* TuyaMCU_FindDefForChannel(int channel) {
return 0;
}
tuyaMCUMapping_t* TuyaMCU_MapIDToChannel(int dpId, int dpType, int channel, int bDPCache, float mul, int inv, float delta, float delta2, float delta3) {
tuyaMCUMapping_t* TuyaMCU_MapIDToChannel(int dpId, int dpType, int channel, int obkFlags, float mul, int inv, float delta, float delta2, float delta3) {
tuyaMCUMapping_t* cur;
cur = TuyaMCU_FindDefForID(dpId);
@@ -351,7 +352,7 @@ tuyaMCUMapping_t* TuyaMCU_MapIDToChannel(int dpId, int dpType, int channel, int
}
cur->dpId = dpId;
cur->dpType = dpType;
cur->bDPCache = bDPCache;
cur->obkFlags = obkFlags;
cur->mult = mul;
cur->delta = delta;
cur->delta2 = delta2;
@@ -873,11 +874,11 @@ commandResult_t TuyaMCU_LinkTuyaMCUOutputToChannel(const void* context, const ch
byte dpType;
int channelID;
byte argsCount;
byte bDPCache;
byte obkFlags;
float mult, delta, delta2, delta3;
byte inv;
// linkTuyaMCUOutputToChannel [dpId] [varType] [channelID] [bDPCache] [mult] [inv] [delta]
// linkTuyaMCUOutputToChannel [dpId] [varType] [channelID] [obkFlags] [mult] [inv] [delta]
// linkTuyaMCUOutputToChannel 1 val 1
Tokenizer_TokenizeString(args, 0);
@@ -897,14 +898,14 @@ commandResult_t TuyaMCU_LinkTuyaMCUOutputToChannel(const void* context, const ch
else {
channelID = Tokenizer_GetArgInteger(2);
}
bDPCache = Tokenizer_GetArgInteger(3);
obkFlags = Tokenizer_GetArgInteger(3);
mult = Tokenizer_GetArgFloatDefault(4, 1.0f);
inv = Tokenizer_GetArgInteger(5);
delta = Tokenizer_GetArgFloatDefault(6, 0.0f);
delta2 = Tokenizer_GetArgFloatDefault(7, 0.0f);
delta3 = Tokenizer_GetArgFloatDefault(8, 0.0f);
TuyaMCU_MapIDToChannel(dpId, dpType, channelID, bDPCache, mult, inv, delta, delta2, delta3);
TuyaMCU_MapIDToChannel(dpId, dpType, channelID, obkFlags, mult, inv, delta, delta2, delta3);
return CMD_RES_OK;
}
@@ -1141,6 +1142,10 @@ void TuyaMCU_ApplyMapping(tuyaMCUMapping_t* mapping, int dpID, int value) {
if (mapping->channel < 0) {
return;
}
if (mapping->obkFlags & OBKTM_FLAG_NOREAD) {
// ignore
return;
}
// map value depending on channel type
switch (CHANNEL_GetType(mapping->channel))
@@ -1206,7 +1211,7 @@ void TuyaMCU_OnChannelChanged(int channel, int iVal) {
}
// dpCaches are sent when requested - TODO - is it correct?
if (mapping->bDPCache) {
if (mapping->obkFlags & OBKTM_FLAG_DPCACHE) {
return;
}
@@ -1854,7 +1859,7 @@ void TuyaMCU_V0_SendDPCacheReply() {
// dpId = 18 Len = 0004 Val V = 1
//
while (map) {
if (map->bDPCache) {
if (map->obkFlags & OBKTM_FLAG_DPCACHE) {
writtenCount++;
// dpID
*p = map->dpId;
@@ -2644,8 +2649,8 @@ void TuyaMCU_Init()
//cmddetail:"fn":"TuyaMCU_Send_SetTime_Current","file":"driver/drv_tuyaMCU.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("tuyaMcu_sendCurTime", TuyaMCU_Send_SetTime_Current, NULL);
//cmddetail:{"name":"linkTuyaMCUOutputToChannel","args":"[dpId][varType][channelID][bDPCache-Optional][mult-optional][bInverse-Optional][delta-Optional][delta2][delta3]",
//cmddetail:"descr":"Used to map between TuyaMCU dpIDs and our internal channels. Mult, inverse and delta are for calibration, they are optional. bDPCache is also optional, you can set it to 1 for battery powered devices, so a variable is set with DPCache, for example a sampling interval for humidity/temperature sensor. Mapping works both ways. DpIDs are per-device, you can get them by sniffing UART communication. Vartypes can also be sniffed from Tuya. VarTypes can be following: 0-raw, 1-bool, 2-value, 3-string, 4-enum, 5-bitmap. Please see [Tuya Docs](https://developer.tuya.com/en/docs/iot/tuya-cloud-universal-serial-port-access-protocol?id=K9hhi0xxtn9cb) for info about TuyaMCU. You can also see our [TuyaMCU Analyzer Tool](https://www.elektroda.com/rtvforum/viewtopic.php?p=20528459#20528459)",
//cmddetail:{"name":"linkTuyaMCUOutputToChannel","args":"[dpId][varType][channelID][obkFlags-Optional][mult-optional][bInverse-Optional][delta-Optional][delta2][delta3]",
//cmddetail:"descr":"Used to map between TuyaMCU dpIDs and our internal channels. Mult, inverse and delta are for calibration, they are optional. obkFlags is also optional, you can set it to 1 for battery powered devices, so a variable is set with DPCache, for example a sampling interval for humidity/temperature sensor. Mapping works both ways. DpIDs are per-device, you can get them by sniffing UART communication. Vartypes can also be sniffed from Tuya. VarTypes can be following: 0-raw, 1-bool, 2-value, 3-string, 4-enum, 5-bitmap. Please see [Tuya Docs](https://developer.tuya.com/en/docs/iot/tuya-cloud-universal-serial-port-access-protocol?id=K9hhi0xxtn9cb) for info about TuyaMCU. You can also see our [TuyaMCU Analyzer Tool](https://www.elektroda.com/rtvforum/viewtopic.php?p=20528459#20528459)",
//cmddetail:"fn":"TuyaMCU_LinkTuyaMCUOutputToChannel","file":"driver/drv_tuyaMCU.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("linkTuyaMCUOutputToChannel", TuyaMCU_LinkTuyaMCUOutputToChannel, NULL);

View File

@@ -1643,55 +1643,58 @@ void CHANNEL_Set_Ex(int ch, int iVal, int iFlags, int ausemovingaverage) {
void CHANNEL_Set(int ch, int iVal, int iFlags) {
CHANNEL_Set_Ex(ch, iVal, iFlags, 0);
}
char *g_channelPingPongs = 0;
void CHANNEL_AddClamped(int ch, int iVal, int min, int max, int bWrapInsteadOfClamp) {
#if 0
int prevValue;
if (ch < 0 || ch >= CHANNEL_MAX) {
addLogAdv(LOG_ERROR, LOG_FEATURE_GENERAL, "CHANNEL_AddClamped: Channel index %i is out of range <0,%i)\n\r", ch, CHANNEL_MAX);
return;
}
prevValue = g_channelValues[ch];
g_channelValues[ch] = g_channelValues[ch] + iVal;
if (bWrapInsteadOfClamp) {
if (g_channelValues[ch] > max)
g_channelValues[ch] = min;
if (g_channelValues[ch] < min)
g_channelValues[ch] = max;
}
else {
if (g_channelValues[ch] > max)
g_channelValues[ch] = max;
if (g_channelValues[ch] < min)
g_channelValues[ch] = min;
}
addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "CHANNEL_AddClamped channel %i has changed to %i\n\r", ch, g_channelValues[ch]);
Channel_OnChanged(ch, prevValue, 0);
#else
void CHANNEL_AddClamped(int ch, int iDelta, int min, int max, int bWrapInsteadOfClamp) {
// we want to support special channel indexes, so it's better to use GET/SET interface
// Special channel indexes are used to access things like dimmer, led colors, etc
iVal = CHANNEL_Get(ch) + iVal;
int newVal;;
if (bWrapInsteadOfClamp) {
if (iVal > max)
iVal = min;
if (iVal < min)
iVal = max;
if (bWrapInsteadOfClamp == 3) {
if (g_channelPingPongs) {
g_channelPingPongs[ch] *= -1;
}
return;
} else if (bWrapInsteadOfClamp == 2) {
// ping-pong logic
if (g_channelPingPongs == 0) {
g_channelPingPongs = (char*)malloc(CHANNEL_MAX);
memset(g_channelPingPongs, 1, CHANNEL_MAX);
}
int prevVal = CHANNEL_Get(ch);
newVal = prevVal + iDelta * g_channelPingPongs[ch];
if (prevVal == min && newVal < min) {
g_channelPingPongs[ch] *= -1;
}
else if (prevVal == max && newVal > max) {
g_channelPingPongs[ch] *= -1;
}
newVal = prevVal + iDelta * g_channelPingPongs[ch];
if (newVal > max) {
newVal = max;
}
else if (newVal < min) {
newVal = min;
}
} else if (bWrapInsteadOfClamp) {
newVal = CHANNEL_Get(ch) + iDelta;
if (newVal > max)
newVal = min;
if (newVal < min)
newVal = max;
}
else {
if (iVal > max)
iVal = max;
if (iVal < min)
iVal = min;
newVal = CHANNEL_Get(ch) + iDelta;
if (newVal > max)
newVal = max;
if (newVal < min)
newVal = min;
}
addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "CHANNEL_AddClamped channel %i has changed to %i\n\r", ch, iVal);
addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL,
"CHANNEL_AddClamped channel %i has changed to %i\n\r", ch, newVal);
CHANNEL_Set(ch, iVal, 0);
#endif
CHANNEL_Set(ch, newVal, 0);
}
void CHANNEL_Add(int ch, int iVal) {
#if 0

View File

@@ -249,6 +249,114 @@ void Test_Commands_Channels() {
SELFTEST_ASSERT_CHANNEL(10, -123);
// clamp test
CMD_ExecuteCommand("SetChannel 1 0", 0);
SELFTEST_ASSERT_CHANNEL(1, 0);
// [ChannelIndex][ValueToAdd][ClampMin][ClampMax][bWrapInsteadOfClamp]
CMD_ExecuteCommand("addChannel 1 10 0 100 0", 0);
SELFTEST_ASSERT_CHANNEL(1, 10);
CMD_ExecuteCommand("addChannel 1 10 0 100 0", 0);
SELFTEST_ASSERT_CHANNEL(1, 20);
CMD_ExecuteCommand("addChannel 1 80 0 100 0", 0);
SELFTEST_ASSERT_CHANNEL(1, 100);
CMD_ExecuteCommand("addChannel 1 80 0 100 0", 0);
SELFTEST_ASSERT_CHANNEL(1, 100);
CMD_ExecuteCommand("addChannel 1 80 0 100 0", 0);
SELFTEST_ASSERT_CHANNEL(1, 100);
CMD_ExecuteCommand("addChannel 1 -1 0 100 0", 0);
SELFTEST_ASSERT_CHANNEL(1, 99);
// wrap test
CMD_ExecuteCommand("addChannel 1 1 0 100 1", 0);
SELFTEST_ASSERT_CHANNEL(1, 100);
CMD_ExecuteCommand("addChannel 1 1 0 100 1", 0);
SELFTEST_ASSERT_CHANNEL(1, 0);
CMD_ExecuteCommand("addChannel 1 1 0 100 1", 0);
SELFTEST_ASSERT_CHANNEL(1, 1);
CMD_ExecuteCommand("addChannel 1 1 0 100 1", 0);
SELFTEST_ASSERT_CHANNEL(1, 2);
CMD_ExecuteCommand("addChannel 1 -1 0 100 1", 0);
SELFTEST_ASSERT_CHANNEL(1, 1);
CMD_ExecuteCommand("addChannel 1 1 0 100 1", 0);
SELFTEST_ASSERT_CHANNEL(1, 2);
CMD_ExecuteCommand("addChannel 1 2 0 100 1", 0);
SELFTEST_ASSERT_CHANNEL(1, 4);
CMD_ExecuteCommand("addChannel 1 10 0 100 1", 0);
SELFTEST_ASSERT_CHANNEL(1, 14);
CMD_ExecuteCommand("addChannel 1 80 0 100 1", 0);
SELFTEST_ASSERT_CHANNEL(1, 94);
CMD_ExecuteCommand("addChannel 1 5 0 100 1", 0);
SELFTEST_ASSERT_CHANNEL(1, 99);
CMD_ExecuteCommand("addChannel 1 5 0 100 1", 0);
// TODO: stop at 100, then go to min?
SELFTEST_ASSERT_CHANNEL(1, 0);
// pingpongtest
SELFTEST_ASSERT_CHANNEL(1, 0);
CMD_ExecuteCommand("addChannel 1 25 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 25);
CMD_ExecuteCommand("addChannel 1 25 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 50);
CMD_ExecuteCommand("addChannel 1 25 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 75);
CMD_ExecuteCommand("addChannel 1 25 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 100);
CMD_ExecuteCommand("addChannel 1 25 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 75);
CMD_ExecuteCommand("addChannel 1 25 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 50);
CMD_ExecuteCommand("addChannel 1 25 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 25);
CMD_ExecuteCommand("addChannel 1 25 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 0);
CMD_ExecuteCommand("addChannel 1 25 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 25);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 49);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 73);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 97);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
// SPECIAL - STOP AT 100
SELFTEST_ASSERT_CHANNEL(1, 100);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 76);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 52);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 28);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 4);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 0);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 24);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 48);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 72);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 96);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 100);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 76);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 52);
// revert dir
CMD_ExecuteCommand("addChannel 1 0 0 100 3", 0);
SELFTEST_ASSERT_CHANNEL(1, 52);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 76);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 100);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 76);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 52);
CMD_ExecuteCommand("addChannel 1 24 0 100 2", 0);
SELFTEST_ASSERT_CHANNEL(1, 28);
// cause error
//SELFTEST_ASSERT_CHANNEL(3, 666);

View File

@@ -168,6 +168,7 @@ void SIM_ClearOBK(const char *flashPath) {
void Win_DoUnitTests() {
//SELFTEST_ASSERT_EXPRESSION("sqrt(4)", 2)
Test_Commands_Channels();
Test_Driver_TCL_AC();
@@ -250,7 +251,6 @@ void Win_DoUnitTests() {
Test_LEDDriver();
Test_LFS();
Test_Scripting();
Test_Commands_Channels();
Test_Command_If();
Test_Tokenizer();
Test_Http();