From 7f3723ee3ae60082ccb556358995e5026e2fad48 Mon Sep 17 00:00:00 2001 From: heiko Date: Sat, 23 Apr 2022 12:03:31 +0200 Subject: [PATCH 1/4] add support for TuyaMCU dimmers * add Tuya_SendState (and typed variants) to set value of a data point * add tuy sendQueryState command to query state of TuyaMCU's data points * add a new channel type "dimmer" (normalized value from 0..100) * run TuyaMCU_OnChannelChanged, whenever a Channel is set to a new value: This updates TuyaMCU's data point linked to the channel * map normalized dimmer value (0..100) to TuyaMCU's dimmer range (tuyaMcu_setDimmerRange) --- src/driver/drv_tuyaMCU.c | 292 ++++++++++++++++++++++++++++++++++++-- src/driver/drv_tuyaMCU.h | 3 +- src/httpserver/http_fns.c | 15 +- src/new_pins.c | 5 + src/new_pins.h | 1 + 5 files changed, 301 insertions(+), 15 deletions(-) diff --git a/src/driver/drv_tuyaMCU.c b/src/driver/drv_tuyaMCU.c index 88e1a8679..52dcf6c33 100644 --- a/src/driver/drv_tuyaMCU.c +++ b/src/driver/drv_tuyaMCU.c @@ -101,6 +101,8 @@ typedef struct tuyaMCUMapping_s { int fnId; // target channel int channel; + // data point type (one of the DP_TYPE_xxx defines) + int dpType; // TODO //int mode; // list @@ -109,6 +111,17 @@ typedef struct tuyaMCUMapping_s { tuyaMCUMapping_t *g_tuyaMappings = 0; +/** + * Dimmer range + * + * Map OpenBK7231T_App's dimmer range of 0..100 to the dimmer range used by TuyMCU. + * Use tuyaMCU_setDimmerrange command to set range used by TuyaMCU. + */ +// minimum dimmer value as reported by TuyaMCU dimmer +int g_dimmerRangeMin = 0; +// maximum dimmer value as reported by TuyaMCU dimmer +int g_dimmerRangeMax = 100; + tuyaMCUMapping_t *TuyaMCU_FindDefForID(int fnId) { tuyaMCUMapping_t *cur; @@ -120,7 +133,20 @@ tuyaMCUMapping_t *TuyaMCU_FindDefForID(int fnId) { } return 0; } -void TuyaMCU_MapIDToChannel(int fnId, int channel) { + +tuyaMCUMapping_t *TuyaMCU_FindDefForChannel(int channel) { + tuyaMCUMapping_t *cur; + + cur = g_tuyaMappings; + while(cur) { + if(cur->channel == channel) + return cur; + cur = cur->next; + } + return 0; +} + +void TuyaMCU_MapIDToChannel(int fnId, int dpType, int channel) { tuyaMCUMapping_t *cur; cur = TuyaMCU_FindDefForID(fnId); @@ -128,6 +154,7 @@ void TuyaMCU_MapIDToChannel(int fnId, int channel) { if(cur == 0) { cur = (tuyaMCUMapping_t*)malloc(sizeof(tuyaMCUMapping_t)); cur->fnId = fnId; + cur->dpType = dpType; cur->next = g_tuyaMappings; g_tuyaMappings = cur; } @@ -215,6 +242,124 @@ void TuyaMCU_SendCommandWithData(byte cmdType, byte *data, int payload_len) { UART_SendByte(check_sum); } +void TuyaMCU_SendState(uint8_t id, uint8_t type, uint8_t* value) +{ + uint16_t payload_len = 4; + uint8_t payload_buffer[8]; + payload_buffer[0] = id; + payload_buffer[1] = type; + switch (type) { + case DP_TYPE_BOOL: + case DP_TYPE_ENUM: + payload_len += 1; + payload_buffer[2] = 0x00; + payload_buffer[3] = 0x01; + payload_buffer[4] = value[0]; + break; + case DP_TYPE_VALUE: + payload_len += 4; + payload_buffer[2] = 0x00; + payload_buffer[3] = 0x04; + payload_buffer[4] = value[3]; + payload_buffer[5] = value[2]; + payload_buffer[6] = value[1]; + payload_buffer[7] = value[0]; + break; + + } + + TuyaMCU_SendCommandWithData(TUYA_CMD_SET_DP, payload_buffer, payload_len); +} + +void TuyaMCU_SendBool(uint8_t id, bool value) +{ + TuyaMCU_SendState(id, DP_TYPE_BOOL, (uint8_t*)&value); +} + +void TuyaMCU_SendValue(uint8_t id, uint32_t value) +{ + TuyaMCU_SendState(id, DP_TYPE_VALUE, (uint8_t*)(&value)); +} + +void TuyaMCU_SendEnum(uint8_t id, uint32_t value) +{ + TuyaMCU_SendState(id, DP_TYPE_ENUM, (uint8_t*)(&value)); +} + +static uint16_t convertHexStringtoBytes (uint8_t * dest, char src[], uint16_t src_len){ + if (NULL == dest || NULL == src || 0 == src_len){ + return 0; + } + + char hexbyte[3]; + hexbyte[2] = 0; + uint16_t i; + + for (i = 0; i < src_len; i++) { + hexbyte[0] = src[2*i]; + hexbyte[1] = src[2*i+1]; + dest[i] = strtol(hexbyte, NULL, 16); + } + + return i; +} + +void TuyaMCU_SendHexString(uint8_t id, char data[]) { + + uint16_t len = strlen(data)/2; + uint16_t payload_len = 4 + len; + uint8_t payload_buffer[payload_len]; + payload_buffer[0] = id; + payload_buffer[1] = DP_TYPE_STRING; + payload_buffer[2] = len >> 8; + payload_buffer[3] = len & 0xFF; + + (void) convertHexStringtoBytes(&payload_buffer[4], data, len); + + TuyaMCU_SendCommandWithData(TUYA_CMD_SET_DP, payload_buffer, payload_len); +} + +void TuyaMCU_SendString(uint8_t id, char data[]) { + + uint16_t len = strlen(data); + uint16_t payload_len = 4 + len; + uint8_t payload_buffer[payload_len]; + payload_buffer[0] = id; + payload_buffer[1] = DP_TYPE_STRING; + payload_buffer[2] = len >> 8; + payload_buffer[3] = len & 0xFF; + + for (uint16_t i = 0; i < len; i++) { + payload_buffer[4+i] = data[i]; + } + + TuyaMCU_SendCommandWithData(TUYA_CMD_SET_DP, payload_buffer, payload_len); +} + +void TuyaMCU_SendRaw(uint8_t id, char data[]) { + char* beginPos = strchr(data, 'x'); + if(!beginPos) { + beginPos = strchr(data, 'X'); + } + if(!beginPos) { + beginPos = data; + } else { + beginPos += 1; + } + uint16_t strSize = strlen(beginPos); + uint16_t len = strSize/2; + uint16_t payload_len = 4 + len; + uint8_t payload_buffer[payload_len]; + payload_buffer[0] = id; + payload_buffer[1] = DP_TYPE_RAW; + payload_buffer[2] = len >> 8; + payload_buffer[3] = len & 0xFF; + + (void) convertHexStringtoBytes(&payload_buffer[4], beginPos, len); + + TuyaMCU_SendCommandWithData(TUYA_CMD_SET_DP, payload_buffer, payload_len); +} + void TuyaMCU_Send_SetTime(struct tm *pTime) { byte payload_buffer[8]; byte tuya_day_of_week; @@ -266,20 +411,22 @@ int TuyaMCU_Send_Hex(const void *context, const char *cmd, const char *args) { } int TuyaMCU_LinkTuyaMCUOutputToChannel(const void *context, const char *cmd, const char *args) { - int dpID; + int dpId; + int dpType; int channelID; - // linkTuyaMCUOutputToChannel dpID channelID [varType] + // linkTuyaMCUOutputToChannel dpId channelID [varType] Tokenizer_TokenizeString(args); - if(Tokenizer_GetArgsCount() < 2) { - addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_LinkTuyaMCUOutputToChannel: requires 2 arguments (dpID, channelIndex)\n"); + if(Tokenizer_GetArgsCount() < 3) { + addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_LinkTuyaMCUOutputToChannel: requires 2 arguments (dpId, dpType, channelIndex)\n"); return -1; } - dpID = Tokenizer_GetArgInteger(0); - channelID = Tokenizer_GetArgInteger(1); + dpId = Tokenizer_GetArgInteger(0); + dpType = Tokenizer_GetArgInteger(1); + channelID = Tokenizer_GetArgInteger(2); - TuyaMCU_MapIDToChannel(dpID,channelID); + TuyaMCU_MapIDToChannel(dpId, dpType, channelID); return 1; } @@ -319,6 +466,60 @@ void TuyaMCU_Send(byte *data, int size) { addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"\nWe sent %i bytes to Tuya MCU\n",size+1); } + +int TuyaMCU_SetDimmerRange(const void *context, const char *cmd, const char *args) { + Tokenizer_TokenizeString(args); + + if(Tokenizer_GetArgsCount() < 2) { + addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"tuyaMcu_setDimmerRange: requires 2 arguments (dimmerRangeMin, dimmerRangeMax)\n"); + return -1; + } + + g_dimmerRangeMin = Tokenizer_GetArgInteger(0); + g_dimmerRangeMax = Tokenizer_GetArgInteger(1); + + return 1; +} + +int TuyaMCU_SendHeartbeat(const void *context, const char *cmd, const char *args) { + TuyaMCU_SendCommandWithData(TUYA_CMD_HEARTBEAT, NULL, 0); + + return 1; +} + +int TuyaMCU_SendQueryState(const void *context, const char *cmd, const char *args) { + TuyaMCU_SendCommandWithData(TUYA_CMD_QUERY_STATE, NULL, 0); + + return 1; +} + +int TuyaMCU_SendStateCmd(const void *context, const char *cmd, const char *args) { + int dpId; + int dpType; + int value; + + Tokenizer_TokenizeString(args); + + if(Tokenizer_GetArgsCount() < 3) { + addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"tuyaMcu_sendState: requires 3 arguments (dpId, dpType, value)\n"); + return -1; + } + + dpId = Tokenizer_GetArgInteger(0); + dpType = Tokenizer_GetArgInteger(1); + value = Tokenizer_GetArgInteger(2); + + TuyaMCU_SendState(dpId, dpType, (uint8_t *)&value); + + return 1; +} + +int TuyaMCU_SendMCUConf(const void *context, const char *cmd, const char *args) { + TuyaMCU_SendCommandWithData(TUYA_CMD_MCU_CONF, NULL, 0); + + return 1; +} + void TuyaMCU_Init() { UART_InitUART(9600); @@ -329,7 +530,11 @@ void TuyaMCU_Init() CMD_RegisterCommand("uartSendHex","",TuyaMCU_Send_Hex, "Sends raw data by TuyaMCU UART, you must write whole packet with checksum yourself", NULL); ///CMD_RegisterCommand("tuyaMcu_sendSimple","",TuyaMCU_Send_Simple, "Appends a 0x55 0xAA header to a data, append a checksum at end and send"); CMD_RegisterCommand("linkTuyaMCUOutputToChannel","",TuyaMCU_LinkTuyaMCUOutputToChannel, "Map value send from TuyaMCU (eg. humidity or temperature) to channel", NULL); - + CMD_RegisterCommand("tuyaMcu_setDimmerRange","",TuyaMCU_SetDimmerRange, "Set dimmer range used by TuyaMCU", NULL); + CMD_RegisterCommand("tuyaMcu_sendHeartbeat","",TuyaMCU_SendHeartbeat, "Send heartbeat to TuyaMCU", NULL); + CMD_RegisterCommand("tuyaMcu_sendQueryState","",TuyaMCU_SendQueryState, "Send query state command", NULL); + CMD_RegisterCommand("tuyaMcu_sendState","",TuyaMCU_SendStateCmd, "Send set state command", NULL); + CMD_RegisterCommand("tuyaMcu_sendMCUConf","",TuyaMCU_SendMCUConf, "Send MCU conf command", NULL); } // ntp_timeZoneOfs 2 // addRepeatingEvent 10 uartSendHex 55AA0008000007 @@ -344,6 +549,7 @@ void TuyaMCU_Init() // void TuyaMCU_ApplyMapping(int fnID, int value) { tuyaMCUMapping_t *mapping; + int mappedValue = value; // find mapping (where to save received data) mapping = TuyaMCU_FindDefForID(fnID); @@ -351,8 +557,72 @@ void TuyaMCU_ApplyMapping(int fnID, int value) { if(mapping == 0){ return; } - CHANNEL_Set(mapping->channel,value,0); + + // map value depending on channel type + switch(CHANNEL_GetType(mapping->channel)) + { + case ChType_Dimmer: + // map TuyaMCU's dimmer range to OpenBK7231T_App's dimmer range 0..100 + mappedValue = ((value - g_dimmerRangeMin) * 100) / (g_dimmerRangeMax - g_dimmerRangeMin); + break; + default: + break; + } + + if (value != mappedValue) { + addLogAdv(LOG_DEBUG, LOG_FEATURE_TUYAMCU,"TuyaMCU_ApplyMapping: mapped value %d (TuyaMCU range) to %d (OpenBK7321T_App range)\n", value, mappedValue); + } + + CHANNEL_Set(mapping->channel,mappedValue,0); } + +void TuyaMCU_OnChannelChanged(int channel, int iVal) { + tuyaMCUMapping_t *mapping; + int mappediVal = iVal; + + // find mapping + mapping = TuyaMCU_FindDefForChannel(channel); + + if(mapping == 0){ + return; + } + + // map value depending on channel type + switch(CHANNEL_GetType(mapping->channel)) + { + case ChType_Dimmer: + // map OpenBK7231T_App's dimmer range 0..100 to TuyaMCU's dimmer range + mappediVal = (((g_dimmerRangeMax - g_dimmerRangeMin) * iVal) / 100) + g_dimmerRangeMin; + break; + default: + break; + } + + if (iVal != mappediVal) { + addLogAdv(LOG_DEBUG, LOG_FEATURE_TUYAMCU,"TuyaMCU_OnChannelChanged: mapped value %d (OpenBK7321T_App range) to %d (TuyaMCU range)\n", iVal, mappediVal); + } + + // send value to TuyaMCU + switch(mapping->dpType) + { + case DP_TYPE_BOOL: + TuyaMCU_SendBool(mapping->fnId, mappediVal != 0); + break; + + case DP_TYPE_ENUM: + TuyaMCU_SendEnum(mapping->fnId, mappediVal); + break; + + case DP_TYPE_VALUE: + TuyaMCU_SendValue(mapping->fnId, mappediVal); + break; + + default: + addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_OnChannelChanged: channel %d: unsupported data point type %d-%s\n", channel, mapping->dpType, TuyaMCU_GetDataTypeString(mapping->dpType)); + break; + } +} + void TuyaMCU_ParseStateMessage(const byte *data, int len) { int ofs; int sectorLen; @@ -365,7 +635,7 @@ void TuyaMCU_ParseStateMessage(const byte *data, int len) { sectorLen = data[ofs + 2] << 8 | data[ofs + 3]; fnId = data[ofs]; dataType = data[ofs+1]; - addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ParseStateMessage: processing command %i, dataType %i-%s and %i data bytes\n", + addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ParseStateMessage: processing dpId %i, dataType %i-%s and %i data bytes\n", fnId, dataType, TuyaMCU_GetDataTypeString(dataType),sectorLen); diff --git a/src/driver/drv_tuyaMCU.h b/src/driver/drv_tuyaMCU.h index eae68a952..eecd7f2e2 100644 --- a/src/driver/drv_tuyaMCU.h +++ b/src/driver/drv_tuyaMCU.h @@ -2,4 +2,5 @@ void TuyaMCU_Init(); void TuyaMCU_RunFrame(); -void TuyaMCU_Send(byte *data, int size); \ No newline at end of file +void TuyaMCU_Send(byte *data, int size); +void TuyaMCU_OnChannelChanged(int channel,int iVal); diff --git a/src/httpserver/http_fns.c b/src/httpserver/http_fns.c index 0a96e923e..98de7d325 100644 --- a/src/httpserver/http_fns.c +++ b/src/httpserver/http_fns.c @@ -136,6 +136,13 @@ int http_fn_index(http_request_t *request) { hprintf128(request,"

Changed pwm %i to %i!

",j,newPWMValue); CHANNEL_Set(j,newPWMValue,1); } + if(http_getArg(request->url,"dim",tmpA,sizeof(tmpA))) { + int newDimmerValue = atoi(tmpA); + http_getArg(request->url,"dimIndex",tmpA,sizeof(tmpA)); + j = atoi(tmpA); + hprintf128(request,"

Changed dimmer %i to %i!

",j,newDimmerValue); + CHANNEL_Set(j,newDimmerValue,1); + } for(i = 0; i < CHANNEL_MAX; i++) { @@ -186,13 +193,15 @@ int http_fn_index(http_request_t *request) { hprintf128(request,"",i); hprintf128(request,"",c,i); } - else if(h_isChannelPWM(i)) { + else if(h_isChannelPWM(i) || (channelType == ChType_Dimmer)) { + // PWM and dimmer both use a slider control + const char *inputName = h_isChannelPWM(i) ? "pwm" : "dim"; int pwmValue; pwmValue = CHANNEL_Get(i); hprintf128(request,"
",i); - hprintf128(request,"",i,pwmValue); - hprintf128(request,"",i); + hprintf128(request,"",inputName,i,pwmValue); + hprintf128(request,"",inputName,i); hprintf128(request,"
",i); diff --git a/src/new_pins.c b/src/new_pins.c index 71337c531..af9e7d5aa 100644 --- a/src/new_pins.c +++ b/src/new_pins.c @@ -9,6 +9,7 @@ // Commands register, execution API and cmd tokenizer #include "cmnds/cmd_public.h" #include "i2c/drv_i2c_public.h" +#include "driver/drv_tuyaMCU.h" #include "hal/hal_pins.h" @@ -404,6 +405,7 @@ static void Channel_OnChanged(int ch, int prevValue) { #ifndef OBK_DISABLE_ALL_DRIVERS I2C_OnChannelChanged(ch,iVal); + TuyaMCU_OnChannelChanged(ch, iVal); #endif for(i = 0; i < PLATFORM_GPIO_MAX; i++) { @@ -475,6 +477,7 @@ void CHANNEL_Add(int ch, int iVal) { Channel_OnChanged(ch,prevValue); } + void CHANNEL_Toggle(int ch) { int prev; @@ -749,6 +752,8 @@ int CHANNEL_ParseChannelType(const char *s) { return ChType_Temperature_div10; if(!stricmp(s,"toggle")) return ChType_Toggle; + if(!stricmp(s,"dimmer") ) + return ChType_Dimmer; if(!stricmp(s,"default") ) return ChType_Default; return ChType_Error; diff --git a/src/new_pins.h b/src/new_pins.h index 8eb0d974c..af81ed6e7 100644 --- a/src/new_pins.h +++ b/src/new_pins.h @@ -39,6 +39,7 @@ enum ChannelType { ChType_Humidity_div10, ChType_Temperature_div10, ChType_Toggle, + ChType_Dimmer, }; From 1d827801df1f307019d338110649520fa09d442a Mon Sep 17 00:00:00 2001 From: heiko Date: Sat, 23 Apr 2022 16:29:50 +0200 Subject: [PATCH 2/4] do not run CHANNEL_OnChanged, after updating a channel with a TuyaMCU data points value * TuyaMCU dimmers like moes smart dimmer module 105 are controlled by a push button. After long button press, TuyaMCU automatically starts dimming slowly from low to high and back to low. This is repeated until the button is released, selecting the current dimmer level. While cycling thorugh the dimming range, TuyaMCU reports the current dimming level in short intervals. We update our Channel with this value, but we must not run CHANNEL_OnChanged, as this will set the same value to TuyaMCUs data point again. However, TuyaMCU did already change its data point value internally, so we would set an old value, which leads to flicker on dimming. --- src/driver/drv_tuyaMCU.c | 2 +- src/new_pins.c | 7 ++++++- src/new_pins.h | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/driver/drv_tuyaMCU.c b/src/driver/drv_tuyaMCU.c index 52dcf6c33..8f11b4b82 100644 --- a/src/driver/drv_tuyaMCU.c +++ b/src/driver/drv_tuyaMCU.c @@ -573,7 +573,7 @@ void TuyaMCU_ApplyMapping(int fnID, int value) { addLogAdv(LOG_DEBUG, LOG_FEATURE_TUYAMCU,"TuyaMCU_ApplyMapping: mapped value %d (TuyaMCU range) to %d (OpenBK7321T_App range)\n", value, mappedValue); } - CHANNEL_Set(mapping->channel,mappedValue,0); + CHANNEL_SetEx(mapping->channel,mappedValue,false,false); } void TuyaMCU_OnChannelChanged(int channel, int iVal) { diff --git a/src/new_pins.c b/src/new_pins.c index af9e7d5aa..41341639b 100644 --- a/src/new_pins.c +++ b/src/new_pins.c @@ -446,6 +446,9 @@ int CHANNEL_Get(int ch) { } void CHANNEL_Set(int ch, int iVal, int bForce) { + CHANNEL_SetEx(ch, iVal, bForce, true); +} +void CHANNEL_SetEx(int ch, int iVal, int bForce, int bRunOnChanged) { int prevValue; if(ch < 0 || ch >= CHANNEL_MAX) { @@ -462,7 +465,9 @@ void CHANNEL_Set(int ch, int iVal, int bForce) { addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL,"CHANNEL_Set channel %i has changed to %i\n\r",ch,iVal); g_channelValues[ch] = iVal; - Channel_OnChanged(ch,prevValue); + if (bRunOnChanged) { + Channel_OnChanged(ch,prevValue); + } } void CHANNEL_Add(int ch, int iVal) { int prevValue; diff --git a/src/new_pins.h b/src/new_pins.h index af81ed6e7..e50418735 100644 --- a/src/new_pins.h +++ b/src/new_pins.h @@ -129,6 +129,7 @@ bool CHANNEL_Check(int ch); void CHANNEL_SetChangeCallback(void (*cb)(int idx, int iVal)); void PIN_SetGenericDoubleClickCallback(void (*cb)(int pinIndex)); void CHANNEL_Set(int ch, int iVal, int bForce); +void CHANNEL_SetEx(int ch, int iVal, int bForce, int bRunOnChanged); void CHANNEL_Add(int ch, int iVal); int CHANNEL_Get(int ch); int CHANNEL_GetRoleForOutputChannel(int ch); From 7ca1849a1f3a3d9a57f66eae8cd2311f521ddbe8 Mon Sep 17 00:00:00 2001 From: heiko Date: Sat, 23 Apr 2022 17:58:47 +0200 Subject: [PATCH 3/4] fix typo in comment --- src/driver/drv_tuyaMCU.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver/drv_tuyaMCU.c b/src/driver/drv_tuyaMCU.c index 8f11b4b82..2b3bc9f58 100644 --- a/src/driver/drv_tuyaMCU.c +++ b/src/driver/drv_tuyaMCU.c @@ -419,7 +419,7 @@ int TuyaMCU_LinkTuyaMCUOutputToChannel(const void *context, const char *cmd, con Tokenizer_TokenizeString(args); if(Tokenizer_GetArgsCount() < 3) { - addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_LinkTuyaMCUOutputToChannel: requires 2 arguments (dpId, dpType, channelIndex)\n"); + addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_LinkTuyaMCUOutputToChannel: requires 3 arguments (dpId, dpType, channelIndex)\n"); return -1; } dpId = Tokenizer_GetArgInteger(0); From 485214e38e7b227d4696b9e9fb007242bb439d35 Mon Sep 17 00:00:00 2001 From: heiko Date: Sat, 23 Apr 2022 18:31:30 +0200 Subject: [PATCH 4/4] revert adding CHANNEL_SetEx function * when setting a channel's value, store it as prevValue in tuya mapping. If we see this value again in TuyaMCU_OnChannelChanged, just do not propagate this value to TuyaMCU again. --- src/driver/drv_tuyaMCU.c | 13 ++++++++++++- src/new_pins.c | 7 +------ src/new_pins.h | 1 - 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/driver/drv_tuyaMCU.c b/src/driver/drv_tuyaMCU.c index 2b3bc9f58..dbca695cc 100644 --- a/src/driver/drv_tuyaMCU.c +++ b/src/driver/drv_tuyaMCU.c @@ -103,6 +103,8 @@ typedef struct tuyaMCUMapping_s { int channel; // data point type (one of the DP_TYPE_xxx defines) int dpType; + // store last channel value to avoid sending it again + int prevValue; // TODO //int mode; // list @@ -155,6 +157,7 @@ void TuyaMCU_MapIDToChannel(int fnId, int dpType, int channel) { cur = (tuyaMCUMapping_t*)malloc(sizeof(tuyaMCUMapping_t)); cur->fnId = fnId; cur->dpType = dpType; + cur->prevValue = 0; cur->next = g_tuyaMappings; g_tuyaMappings = cur; } @@ -573,7 +576,9 @@ void TuyaMCU_ApplyMapping(int fnID, int value) { addLogAdv(LOG_DEBUG, LOG_FEATURE_TUYAMCU,"TuyaMCU_ApplyMapping: mapped value %d (TuyaMCU range) to %d (OpenBK7321T_App range)\n", value, mappedValue); } - CHANNEL_SetEx(mapping->channel,mappedValue,false,false); + mapping->prevValue = mappedValue; + + CHANNEL_Set(mapping->channel,mappedValue,false); } void TuyaMCU_OnChannelChanged(int channel, int iVal) { @@ -587,6 +592,12 @@ void TuyaMCU_OnChannelChanged(int channel, int iVal) { return; } + // this might be a callback from CHANNEL_Set in TuyaMCU_ApplyMapping. If we should set exactly the + // same value, skip it + if (mapping->prevValue == iVal) { + return; + } + // map value depending on channel type switch(CHANNEL_GetType(mapping->channel)) { diff --git a/src/new_pins.c b/src/new_pins.c index 41341639b..af9e7d5aa 100644 --- a/src/new_pins.c +++ b/src/new_pins.c @@ -446,9 +446,6 @@ int CHANNEL_Get(int ch) { } void CHANNEL_Set(int ch, int iVal, int bForce) { - CHANNEL_SetEx(ch, iVal, bForce, true); -} -void CHANNEL_SetEx(int ch, int iVal, int bForce, int bRunOnChanged) { int prevValue; if(ch < 0 || ch >= CHANNEL_MAX) { @@ -465,9 +462,7 @@ void CHANNEL_SetEx(int ch, int iVal, int bForce, int bRunOnChanged) { addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL,"CHANNEL_Set channel %i has changed to %i\n\r",ch,iVal); g_channelValues[ch] = iVal; - if (bRunOnChanged) { - Channel_OnChanged(ch,prevValue); - } + Channel_OnChanged(ch,prevValue); } void CHANNEL_Add(int ch, int iVal) { int prevValue; diff --git a/src/new_pins.h b/src/new_pins.h index e50418735..af81ed6e7 100644 --- a/src/new_pins.h +++ b/src/new_pins.h @@ -129,7 +129,6 @@ bool CHANNEL_Check(int ch); void CHANNEL_SetChangeCallback(void (*cb)(int idx, int iVal)); void PIN_SetGenericDoubleClickCallback(void (*cb)(int pinIndex)); void CHANNEL_Set(int ch, int iVal, int bForce); -void CHANNEL_SetEx(int ch, int iVal, int bForce, int bRunOnChanged); void CHANNEL_Add(int ch, int iVal); int CHANNEL_Get(int ch); int CHANNEL_GetRoleForOutputChannel(int ch);