diff --git a/src/cmnds/cmd_channels.c b/src/cmnds/cmd_channels.c
index 45c0b160f..66976a785 100644
--- a/src/cmnds/cmd_channels.c
+++ b/src/cmnds/cmd_channels.c
@@ -148,14 +148,17 @@ static int CMD_GetChannel(const void *context, const char *cmd, const char *args
}
static int CMD_GetReadings(const void *context, const char *cmd, const char *args, int cmdFlags){
#ifndef OBK_DISABLE_ALL_DRIVERS
- char tmp[64];
+ char tmp[96];
float v, c, p;
+ float e, elh;
v = DRV_GetReading(OBK_VOLTAGE);
c = DRV_GetReading(OBK_CURRENT);
p = DRV_GetReading(OBK_POWER);
+ e = DRV_GetReading(OBK_CONSUMPTION_TOTAL);
+ elh = DRV_GetReading(OBK_CONSUMPTION_LAST_HOUR);
- sprintf(tmp, "%f %f %f",v,c,p);
+ sprintf(tmp, "%f %f %f %f %f",v,c,p,e,elh);
if(cmdFlags & COMMAND_FLAG_SOURCE_TCP) {
ADDLOG_INFO(LOG_FEATURE_RAW, tmp);
diff --git a/src/cmnds/cmd_eventHandlers.c b/src/cmnds/cmd_eventHandlers.c
index ff68e1b2e..a17afd09d 100644
--- a/src/cmnds/cmd_eventHandlers.c
+++ b/src/cmnds/cmd_eventHandlers.c
@@ -122,6 +122,10 @@ static int EVENT_ParseEventName(const char *s) {
return CMD_EVENT_PIN_ONDBLCLICK;
if(!stricmp(s,"OnChannelChange"))
return CMD_EVENT_CHANNEL_ONCHANGE;
+ if(!stricmp(s,"energycounter"))
+ return CMD_EVENT_CHANGE_CONSUMPTION_TOTAL;
+ if(!stricmp(s,"energycounter_last_hour"))
+ return CMD_EVENT_CHANGE_CONSUMPTION_LAST_HOUR;
return CMD_EVENT_NONE;
}
static bool EVENT_EvaluateCondition(int code, int argument, int next) {
diff --git a/src/cmnds/cmd_public.h b/src/cmnds/cmd_public.h
index e34429975..e14c8abf1 100644
--- a/src/cmnds/cmd_public.h
+++ b/src/cmnds/cmd_public.h
@@ -42,6 +42,8 @@ enum EventCode {
CMD_EVENT_CHANGE_VOLTAGE, // must match order in drv_bl0942.c
CMD_EVENT_CHANGE_CURRENT,
CMD_EVENT_CHANGE_POWER,
+ CMD_EVENT_CHANGE_CONSUMPTION_TOTAL,
+ CMD_EVENT_CHANGE_CONSUMPTION_LAST_HOUR,
// this is for ToggleChannelOnToggle
CMD_EVENT_PIN_ONTOGGLE,
diff --git a/src/driver/drv_bl_shared.c b/src/driver/drv_bl_shared.c
index 6b2e871d3..b88e3f11b 100644
--- a/src/driver/drv_bl_shared.c
+++ b/src/driver/drv_bl_shared.c
@@ -9,6 +9,7 @@
#include "drv_local.h"
#include "drv_uart.h"
#include "../httpserver/new_http.h"
+#include "../cJSON/cJSON.h"
int stat_updatesSkipped = 0;
int stat_updatesSent = 0;
@@ -28,49 +29,88 @@ float lastSentValues[OBK_NUM_MEASUREMENTS];
float energyCounter = 0.0f;
portTickType energyCounterStamp;
+float energyCounterMinutes[60];
+portTickType energyCounterMinutesStamp;
+long energyCounterMinutesIndex;
+
// how much update frames has passed without sending MQTT update of read values?
int noChangeFrames[OBK_NUM_MEASUREMENTS];
int noChangeFrameEnergyCounter;
float lastSentEnergyCounterValue = 0.0f;
float changeSendThresholdEnergy = 0.1f;
+float lastSentEnergyCounterLastHour = 0.0f;
// how much of value have to change in order to be send over MQTT again?
int changeSendThresholds[OBK_NUM_MEASUREMENTS] = {
- 0.25f, // voltage - OBK_VOLTAGE
- 0.002f, // current - OBK_CURRENT
- 0.25f, // power - OBK_POWER
+ 0.25f, // voltage - OBK_VOLTAGE
+ 0.002f, // current - OBK_CURRENT
+ 0.25f, // power - OBK_POWER
};
int changeSendAlwaysFrames = 60;
int changeDoNotSendMinFrames = 5;
-void BL09XX_AppendInformationToHTTPIndexPage(http_request_t *request) {
- char tmp[128];
- const char *mode;
+void BL09XX_AppendInformationToHTTPIndexPage(http_request_t *request)
+{
+ int i;
+ char tmp[128];
+ const char *mode;
+ char number[16];
- if(DRV_IsRunning("BL0937")) {
- mode = "BL0937";
- } else if(DRV_IsRunning("BL0942")) {
- mode = "BL0942";
- } else {
- mode = "PWR";
- }
- sprintf(tmp, "
%s Voltage=%f, Current=%f, Power=%f, Consumption=%f (changes sent %i, skipped %i)
",
- mode, lastReadings[OBK_VOLTAGE],lastReadings[OBK_CURRENT], lastReadings[OBK_POWER],
+ if(DRV_IsRunning("BL0937")) {
+ mode = "BL0937";
+ } else if(DRV_IsRunning("BL0942")) {
+ mode = "BL0942";
+ } else {
+ mode = "PWR";
+ }
+ sprintf(tmp, "%s Voltage=%f, Current=%f, Power=%f, Consumption=%1.1f Wh (changes sent %i, skipped %i)
",
+ mode, lastReadings[OBK_VOLTAGE],lastReadings[OBK_CURRENT], lastReadings[OBK_POWER],
energyCounter, stat_updatesSent, stat_updatesSkipped);
hprintf128(request,tmp);
+ /********************************************************************************************************************/
+ sprintf(tmp, "Last Hour Statistics
Consumption: %1.1f Wh
", DRV_GetReading(OBK_CONSUMPTION_LAST_HOUR));
+ hprintf128(request,tmp);
+ sprintf(tmp, "History per minute:
");
+ hprintf128(request,tmp);
+ memset(tmp,0,128);
+ for(i=0; i<60; i++)
+ {
+ if ((i%20)==0)
+ {
+ sprintf(number,"%1.1f", energyCounterMinutes[i]);
+ } else {
+ sprintf(number,", %1.1f", energyCounterMinutes[i]);
+ }
+ strcat(tmp, number);
+ if ((i%20)==19)
+ {
+ strcat(tmp, "
");
+ hprintf128(request,tmp);
+ memset(tmp,0,128);
+ }
+ }
+ hprintf128(request,"History Index: %d
", energyCounterMinutesIndex);
+ /********************************************************************************************************************/
}
int BL0937_ResetEnergyCounter(const void *context, const char *cmd, const char *args, int cmdFlags)
{
float value;
+ int i;
if(args==0||*args==0)
{
energyCounter = 0.0f;
energyCounterStamp = xTaskGetTickCount();
+ for(i = 0; i < 60; i++)
+ {
+ energyCounterMinutes[i] = 0.0;
+ }
+ energyCounterMinutesStamp = xTaskGetTickCount();
+ energyCounterMinutesIndex = 0;
} else {
value = atof(args);
energyCounter = value;
@@ -81,14 +121,18 @@ int BL0937_ResetEnergyCounter(const void *context, const char *cmd, const char *
void BL_ProcessUpdate(float voltage, float current, float power)
{
- int i;
+ int i;
float energy;
int xPassedTicks;
+ cJSON* root;
+ cJSON* stats;
+ char *msg;
+
// those are final values, like 230V
- lastReadings[OBK_POWER] = power;
- lastReadings[OBK_VOLTAGE] = voltage;
- lastReadings[OBK_CURRENT] = current;
+ lastReadings[OBK_POWER] = power;
+ lastReadings[OBK_VOLTAGE] = voltage;
+ lastReadings[OBK_CURRENT] = current;
xPassedTicks = (int)(xTaskGetTickCount() - energyCounterStamp);
if (xPassedTicks <= 0)
@@ -100,65 +144,132 @@ void BL_ProcessUpdate(float voltage, float current, float power)
energyCounter += energy;
energyCounterStamp = xTaskGetTickCount();
- for(i = 0; i < OBK_NUM_MEASUREMENTS; i++)
+ if ((xTaskGetTickCount() - energyCounterMinutesStamp) >= (60000 / portTICK_PERIOD_MS))
{
- // send update only if there was a big change or if certain time has passed
- // Do not send message with every measurement.
- if ( ((abs(lastSentValues[i]-lastReadings[i]) > changeSendThresholds[i]) &&
- (noChangeFrames[i] >= changeDoNotSendMinFrames)) ||
- (noChangeFrames[i] >= changeSendAlwaysFrames) )
+ root = cJSON_CreateObject();
+ cJSON_AddNumberToObject(root, "uptime", Time_getUpTimeSeconds());
+ cJSON_AddNumberToObject(root, "consumption_total", energyCounter );
+ cJSON_AddNumberToObject(root, "consumption_last_hour", DRV_GetReading(OBK_CONSUMPTION_LAST_HOUR));
+ cJSON_AddNumberToObject(root, "consumption_stat_index", energyCounterMinutesIndex);
+
+ stats = cJSON_CreateArray();
+ for(i = 0; i < 60; i++)
{
- noChangeFrames[i] = 0;
- if(i == OBK_CURRENT)
+ cJSON_AddItemToArray(stats, cJSON_CreateNumber(energyCounterMinutes[i]));
+ }
+ cJSON_AddItemToObject(root, "consumption_minutes", stats);
+
+ msg = cJSON_Print(root);
+ cJSON_Delete(root);
+
+ MQTT_PublishMain_StringString(counter_mqttNames[2], msg, 0);
+ stat_updatesSent++;
+ os_free(msg);
+
+ for (i=59;i>0;i--)
+ {
+ energyCounterMinutes[i] = energyCounterMinutes[i-1];
+ }
+ energyCounterMinutes[0] = 0.0;
+ energyCounterMinutesStamp = xTaskGetTickCount();
+ energyCounterMinutesIndex++;
+
+ MQTT_PublishMain_StringFloat(counter_mqttNames[1], DRV_GetReading(OBK_CONSUMPTION_LAST_HOUR));
+ EventHandlers_ProcessVariableChange_Integer(CMD_EVENT_CHANGE_CONSUMPTION_LAST_HOUR, lastSentEnergyCounterLastHour, DRV_GetReading(OBK_CONSUMPTION_LAST_HOUR));
+ lastSentEnergyCounterLastHour = DRV_GetReading(OBK_CONSUMPTION_LAST_HOUR);
+ stat_updatesSent++;
+ }
+ energyCounterMinutes[0] += energy;
+
+ for(i = 0; i < OBK_NUM_MEASUREMENTS; i++)
+ {
+ // send update only if there was a big change or if certain time has passed
+ // Do not send message with every measurement.
+ if ( ((abs(lastSentValues[i]-lastReadings[i]) > changeSendThresholds[i]) &&
+ (noChangeFrames[i] >= changeDoNotSendMinFrames)) ||
+ (noChangeFrames[i] >= changeSendAlwaysFrames) )
+ {
+ noChangeFrames[i] = 0;
+ if(i == OBK_CURRENT)
{
- int prev_mA, now_mA;
- prev_mA = lastSentValues[i] * 1000;
- now_mA = lastReadings[i] * 1000;
- EventHandlers_ProcessVariableChange_Integer(CMD_EVENT_CHANGE_CURRENT, prev_mA,now_mA);
- } else {
- EventHandlers_ProcessVariableChange_Integer(CMD_EVENT_CHANGE_VOLTAGE+i, lastSentValues[i], lastReadings[i]);
- }
- lastSentValues[i] = lastReadings[i];
- MQTT_PublishMain_StringFloat(sensor_mqttNames[i],lastReadings[i]);
- stat_updatesSent++;
- } else {
- // no change frame
- noChangeFrames[i]++;
- stat_updatesSkipped++;
- }
+ int prev_mA, now_mA;
+ prev_mA = lastSentValues[i] * 1000;
+ now_mA = lastReadings[i] * 1000;
+ EventHandlers_ProcessVariableChange_Integer(CMD_EVENT_CHANGE_CURRENT, prev_mA,now_mA);
+ } else {
+ EventHandlers_ProcessVariableChange_Integer(CMD_EVENT_CHANGE_VOLTAGE+i, lastSentValues[i], lastReadings[i]);
+ }
+ lastSentValues[i] = lastReadings[i];
+ MQTT_PublishMain_StringFloat(sensor_mqttNames[i],lastReadings[i]);
+ stat_updatesSent++;
+ } else {
+ // no change frame
+ noChangeFrames[i]++;
+ stat_updatesSkipped++;
+ }
}
if ( (((energyCounter - lastSentEnergyCounterValue) >= changeSendThresholdEnergy) &&
(noChangeFrameEnergyCounter >= changeDoNotSendMinFrames)) ||
(noChangeFrameEnergyCounter >= changeSendAlwaysFrames) )
{
+ MQTT_PublishMain_StringFloat(counter_mqttNames[0], energyCounter);
+ EventHandlers_ProcessVariableChange_Integer(CMD_EVENT_CHANGE_CONSUMPTION_TOTAL, lastSentEnergyCounterValue, energyCounter);
lastSentEnergyCounterValue = energyCounter;
- MQTT_PublishMain_StringFloat("energycounter", energyCounter);
noChangeFrameEnergyCounter = 0;
stat_updatesSent++;
+ MQTT_PublishMain_StringFloat(counter_mqttNames[1], DRV_GetReading(OBK_CONSUMPTION_LAST_HOUR));
+ EventHandlers_ProcessVariableChange_Integer(CMD_EVENT_CHANGE_CONSUMPTION_LAST_HOUR, lastSentEnergyCounterLastHour, DRV_GetReading(OBK_CONSUMPTION_LAST_HOUR));
+ lastSentEnergyCounterLastHour = DRV_GetReading(OBK_CONSUMPTION_LAST_HOUR);
+ stat_updatesSent++;
} else {
noChangeFrameEnergyCounter++;
stat_updatesSkipped++;
}
}
-void BL_Shared_Init()
+void BL_Shared_Init()
{
- int i;
+ int i;
- for(i = 0; i < OBK_NUM_MEASUREMENTS; i++)
+ for(i = 0; i < OBK_NUM_MEASUREMENTS; i++)
{
- noChangeFrames[i] = 0;
- lastReadings[i] = 0;
- }
+ noChangeFrames[i] = 0;
+ lastReadings[i] = 0;
+ }
noChangeFrameEnergyCounter = 0;
energyCounterStamp = xTaskGetTickCount();
+
+ for(i = 0; i < 60; i++)
+ {
+ energyCounterMinutes[i] = 0.0;
+ }
+ energyCounterMinutesStamp = xTaskGetTickCount();
+ energyCounterMinutesIndex = 0;
}
// OBK_POWER etc
float DRV_GetReading(int type)
{
- return lastReadings[type];
+ int i;
+ float hourly_sum = 0.0;
+ switch (type)
+ {
+ case OBK_VOLTAGE: // must match order in cmd_public.h
+ case OBK_CURRENT:
+ case OBK_POWER:
+ return lastReadings[type];
+ case OBK_CONSUMPTION_TOTAL:
+ return energyCounter;
+ case OBK_CONSUMPTION_LAST_HOUR:
+ for(i=0;i<60;i++)
+ {
+ hourly_sum += energyCounterMinutes[i];
+ }
+ return hourly_sum;
+ default:
+ break;
+ }
+ return 0.0f;
}
-
diff --git a/src/driver/drv_main.c b/src/driver/drv_main.c
index ddec5d081..6d428a945 100644
--- a/src/driver/drv_main.c
+++ b/src/driver/drv_main.c
@@ -18,6 +18,12 @@ const char *sensor_mqttNames[OBK_NUM_MEASUREMENTS] = {
"power"
};
+const char *counter_mqttNames[OBK_NUM_COUNTERS] = {
+ "energycounter",
+ "energycounter_last_hour",
+ "consumption_stats"
+};
+
typedef struct driver_s {
const char *name;
void (*initFunc)();
@@ -54,7 +60,7 @@ static driver_t g_drivers[] = {
{ "tmSensor", TuyaMCU_Sensor_Init, TuyaMCU_Sensor_RunFrame, NULL, NULL, NULL, NULL, false }
};
-static int g_numDrivers = sizeof(g_drivers)/sizeof(g_drivers[0]);
+static const int g_numDrivers = sizeof(g_drivers)/sizeof(g_drivers[0]);
bool DRV_IsRunning(const char *name) {
int i;
@@ -144,7 +150,7 @@ void DRV_StopDriver(const char *name) {
if(g_drivers[i].stopFunc != 0) {
g_drivers[i].stopFunc();
}
- g_drivers[i].bLoaded = 0;
+ g_drivers[i].bLoaded = false;
addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"Drv %s has been stopped.\n",name);
break ;
} else {
diff --git a/src/driver/drv_public.h b/src/driver/drv_public.h
index 490ec5591..afe85c19b 100644
--- a/src/driver/drv_public.h
+++ b/src/driver/drv_public.h
@@ -9,8 +9,19 @@ enum {
OBK_NUM_MEASUREMENTS,
};
+enum {
+ OBK_CONSUMPTION_TOTAL = OBK_NUM_MEASUREMENTS,
+ OBK_CONSUMPTION_LAST_HOUR,
+ OBK_CONSUMPTION_STATS,
+ OBK_NUM_EMUNS_MAX
+};
+
+#define OBK_NUM_COUNTERS (OBK_NUM_EMUNS_MAX-OBK_NUM_MEASUREMENTS)
+#define OBK_NUM_SENSOR_COUNT OBK_NUM_EMUNS_MAX
+
// MQTT names of sensors (voltage, current, power)
extern const char *sensor_mqttNames[];
+extern const char *counter_mqttNames[];
void DRV_Generic_Init();
void DRV_AppendInformationToHTTPIndexPage(http_request_t *request);
diff --git a/src/driver/drv_tuyaMCU.c b/src/driver/drv_tuyaMCU.c
index 3a5adf011..9f4be84ba 100644
--- a/src/driver/drv_tuyaMCU.c
+++ b/src/driver/drv_tuyaMCU.c
@@ -52,19 +52,19 @@ void TuyaMCU_RunFrame();
const char *TuyaMCU_GetDataTypeString(int dpId){
- if(DP_TYPE_RAW == dpId)
- return "DP_TYPE_RAW";
- if(DP_TYPE_BOOL == dpId)
- return "DP_TYPE_BOOL";
- if(DP_TYPE_VALUE == dpId)
- return "DP_TYPE_VALUE";
- if(DP_TYPE_STRING == dpId)
- return "DP_TYPE_STRING";
- if(DP_TYPE_ENUM == dpId)
- return "DP_TYPE_ENUM";
- if(DP_TYPE_BITMAP == dpId)
- return "DP_TYPE_BITMAP";
- return "DP_ERROR";
+ if(DP_TYPE_RAW == dpId)
+ return "DP_TYPE_RAW";
+ if(DP_TYPE_BOOL == dpId)
+ return "DP_TYPE_BOOL";
+ if(DP_TYPE_VALUE == dpId)
+ return "DP_TYPE_VALUE";
+ if(DP_TYPE_STRING == dpId)
+ return "DP_TYPE_STRING";
+ if(DP_TYPE_ENUM == dpId)
+ return "DP_TYPE_ENUM";
+ if(DP_TYPE_BITMAP == dpId)
+ return "DP_TYPE_BITMAP";
+ return "DP_ERROR";
}
// from http_fns. should move to a utils file.
extern unsigned char hexbyte( const char* hex );
@@ -73,55 +73,55 @@ extern unsigned char hexbyte( const char* hex );
const char *TuyaMCU_GetCommandTypeLabel(int t) {
- if(t == TUYA_CMD_HEARTBEAT)
- return "Hearbeat";
- if(t == TUYA_CMD_QUERY_PRODUCT)
- return "QueryProductInformation";
- if(t == TUYA_CMD_MCU_CONF)
- return "MCUconf";
- if(t == TUYA_CMD_WIFI_STATE)
- return "WiFiState";
- if(t == TUYA_CMD_WIFI_RESET)
- return "WiFiReset";
- if(t == TUYA_CMD_WIFI_SELECT)
- return "WiFiSelect";
- if(t == TUYA_CMD_SET_DP)
- return "SetDP";
- if(t == TUYA_CMD_STATE)
- return "State";
- if(t == TUYA_CMD_QUERY_STATE)
- return "QueryState";
- if(t == TUYA_CMD_SET_TIME)
- return "SetTime";
- return "Unknown";
+ if(t == TUYA_CMD_HEARTBEAT)
+ return "Hearbeat";
+ if(t == TUYA_CMD_QUERY_PRODUCT)
+ return "QueryProductInformation";
+ if(t == TUYA_CMD_MCU_CONF)
+ return "MCUconf";
+ if(t == TUYA_CMD_WIFI_STATE)
+ return "WiFiState";
+ if(t == TUYA_CMD_WIFI_RESET)
+ return "WiFiReset";
+ if(t == TUYA_CMD_WIFI_SELECT)
+ return "WiFiSelect";
+ if(t == TUYA_CMD_SET_DP)
+ return "SetDP";
+ if(t == TUYA_CMD_STATE)
+ return "State";
+ if(t == TUYA_CMD_QUERY_STATE)
+ return "QueryState";
+ if(t == TUYA_CMD_SET_TIME)
+ return "SetTime";
+ return "Unknown";
}
typedef struct rtcc_s {
- uint8_t second;
- uint8_t minute;
- uint8_t hour;
- uint8_t day_of_week; // sunday is day 1
- uint8_t day_of_month;
- uint8_t month;
- char name_of_month[4];
- uint16_t day_of_year;
- uint16_t year;
- uint32_t days;
- uint32_t valid;
+ uint8_t second;
+ uint8_t minute;
+ uint8_t hour;
+ uint8_t day_of_week; // sunday is day 1
+ uint8_t day_of_month;
+ uint8_t month;
+ char name_of_month[4];
+ uint16_t day_of_year;
+ uint16_t year;
+ uint32_t days;
+ uint32_t valid;
} rtcc_t;
typedef struct tuyaMCUMapping_s {
- // internal Tuya variable index
- int fnId;
- // target channel
- 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
- struct tuyaMCUMapping_s *next;
+ // internal Tuya variable index
+ int fnId;
+ // target channel
+ 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
+ struct tuyaMCUMapping_s *next;
} tuyaMCUMapping_t;
tuyaMCUMapping_t *g_tuyaMappings = 0;
@@ -140,119 +140,130 @@ int g_dimmerRangeMax = 100;
// serial baud rate used to communicate with the TuyaMCU
int g_baudRate = 9600;
-tuyaMCUMapping_t *TuyaMCU_FindDefForID(int fnId) {
- tuyaMCUMapping_t *cur;
+static bool heartbeat_valid = false;
+static int heartbeat_timer = 0;
+static int heartbeat_counter = 0;
+static bool product_information_valid = false;
+static char *prod_info = NULL;
+static bool working_mode_valid = false;
+static bool wifi_state_valid = false;
+static bool wifi_state = false;
+static bool self_processing_mode = true;
+static bool state_updated = false;
- cur = g_tuyaMappings;
- while(cur) {
- if(cur->fnId == fnId)
- return cur;
- cur = cur->next;
- }
- return 0;
+tuyaMCUMapping_t *TuyaMCU_FindDefForID(int fnId) {
+ tuyaMCUMapping_t *cur;
+
+ cur = g_tuyaMappings;
+ while(cur) {
+ if(cur->fnId == fnId)
+ return cur;
+ cur = cur->next;
+ }
+ return 0;
}
tuyaMCUMapping_t *TuyaMCU_FindDefForChannel(int channel) {
- tuyaMCUMapping_t *cur;
+ tuyaMCUMapping_t *cur;
- cur = g_tuyaMappings;
- while(cur) {
- if(cur->channel == channel)
- return cur;
- cur = cur->next;
- }
- return 0;
+ 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;
+ tuyaMCUMapping_t *cur;
- cur = TuyaMCU_FindDefForID(fnId);
+ cur = TuyaMCU_FindDefForID(fnId);
- if(cur == 0) {
- cur = (tuyaMCUMapping_t*)malloc(sizeof(tuyaMCUMapping_t));
- cur->fnId = fnId;
- cur->dpType = dpType;
- cur->prevValue = 0;
- cur->next = g_tuyaMappings;
- g_tuyaMappings = cur;
- }
+ if(cur == 0) {
+ cur = (tuyaMCUMapping_t*)malloc(sizeof(tuyaMCUMapping_t));
+ cur->fnId = fnId;
+ cur->dpType = dpType;
+ cur->prevValue = 0;
+ cur->next = g_tuyaMappings;
+ g_tuyaMappings = cur;
+ }
- cur->channel = channel;
+ cur->channel = channel;
}
// header version command lenght data checksum
-// 55AA 00 00 0000 xx 00
+// 55AA 00 00 0000 xx 00
#define MIN_TUYAMCU_PACKET_SIZE (2+1+1+2+1)
int UART_TryToGetNextTuyaPacket(byte *out, int maxSize) {
- int cs;
- int len, i;
- int c_garbage_consumed = 0;
- byte a, b, version, command, lena, lenb;
- char printfSkipDebug[256];
- char buffer2[8];
+ int cs;
+ int len, i;
+ int c_garbage_consumed = 0;
+ byte a, b, version, command, lena, lenb;
+ char printfSkipDebug[256];
+ char buffer2[8];
- printfSkipDebug[0] = 0;
+ printfSkipDebug[0] = 0;
- cs = UART_GetDataSize();
+ cs = UART_GetDataSize();
- if(cs < MIN_TUYAMCU_PACKET_SIZE) {
- return 0;
- }
- // skip garbage data (should not happen)
- while(cs > 0) {
- a = UART_GetNextByte(0);
- b = UART_GetNextByte(1);
- if(a != 0x55 || b != 0xAA) {
- UART_ConsumeBytes(1);
- if(c_garbage_consumed + 2 < sizeof(printfSkipDebug)) {
- sprintf(buffer2,"%02X ",a);
- strcat_safe(printfSkipDebug,buffer2,sizeof(printfSkipDebug));
- }
- c_garbage_consumed++;
- cs--;
- } else {
- break;
- }
- }
- if(c_garbage_consumed > 0){
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"Consumed %i unwanted non-header byte in Tuya MCU buffer\n", c_garbage_consumed);
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"Skipped data (part) %s\n", printfSkipDebug);
- }
- if(cs < MIN_TUYAMCU_PACKET_SIZE) {
- return 0;
- }
- a = UART_GetNextByte(0);
- b = UART_GetNextByte(1);
- if(a != 0x55 || b != 0xAA) {
- return 0;
- }
- version = UART_GetNextByte(2);
- command = UART_GetNextByte(3);
- lena = UART_GetNextByte(4); // hi
- lenb = UART_GetNextByte(5); // lo
- len = lenb | lena >> 8;
- // now check if we have received whole packet
- len += 2 + 1 + 1 + 2 + 1; // header 2 bytes, version, command, lenght, chekcusm
- if(cs >= len) {
- int ret;
- // can packet fit into the buffer?
- if(len <= maxSize) {
- for(i = 0; i < len; i++) {
- out[i] = UART_GetNextByte(i);
- }
- ret = len;
- } else {
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU packet too large, %i > %i\n", len, maxSize);
- ret = 0;
- }
- // consume whole packet (but don't touch next one, if any)
- UART_ConsumeBytes(len);
- return ret;
- }
- return 0;
+ if(cs < MIN_TUYAMCU_PACKET_SIZE) {
+ return 0;
+ }
+ // skip garbage data (should not happen)
+ while(cs > 0) {
+ a = UART_GetNextByte(0);
+ b = UART_GetNextByte(1);
+ if(a != 0x55 || b != 0xAA) {
+ UART_ConsumeBytes(1);
+ if(c_garbage_consumed + 2 < sizeof(printfSkipDebug)) {
+ sprintf(buffer2,"%02X ",a);
+ strcat_safe(printfSkipDebug,buffer2,sizeof(printfSkipDebug));
+ }
+ c_garbage_consumed++;
+ cs--;
+ } else {
+ break;
+ }
+ }
+ if(c_garbage_consumed > 0){
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"Consumed %i unwanted non-header byte in Tuya MCU buffer\n", c_garbage_consumed);
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"Skipped data (part) %s\n", printfSkipDebug);
+ }
+ if(cs < MIN_TUYAMCU_PACKET_SIZE) {
+ return 0;
+ }
+ a = UART_GetNextByte(0);
+ b = UART_GetNextByte(1);
+ if(a != 0x55 || b != 0xAA) {
+ return 0;
+ }
+ version = UART_GetNextByte(2);
+ command = UART_GetNextByte(3);
+ lena = UART_GetNextByte(4); // hi
+ lenb = UART_GetNextByte(5); // lo
+ len = lenb | lena >> 8;
+ // now check if we have received whole packet
+ len += 2 + 1 + 1 + 2 + 1; // header 2 bytes, version, command, lenght, chekcusm
+ if(cs >= len) {
+ int ret;
+ // can packet fit into the buffer?
+ if(len <= maxSize) {
+ for(i = 0; i < len; i++) {
+ out[i] = UART_GetNextByte(i);
+ }
+ ret = len;
+ } else {
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU packet too large, %i > %i\n", len, maxSize);
+ ret = 0;
+ }
+ // consume whole packet (but don't touch next one, if any)
+ UART_ConsumeBytes(len);
+ return ret;
+ }
+ return 0;
}
@@ -260,22 +271,22 @@ int UART_TryToGetNextTuyaPacket(byte *out, int maxSize) {
// append header, len, everything, checksum
void TuyaMCU_SendCommandWithData(byte cmdType, byte *data, int payload_len) {
- int i;
+ int i;
- byte check_sum = (0xFF + cmdType + (payload_len >> 8) + (payload_len & 0xFF));
- UART_InitUART(g_baudRate);
- UART_SendByte(0x55);
- UART_SendByte(0xAA);
- UART_SendByte(0x00); // version 00
- UART_SendByte(cmdType); // version 00
- UART_SendByte(payload_len >> 8); // following data length (Hi)
- UART_SendByte(payload_len & 0xFF); // following data length (Lo)
- for(i = 0; i < payload_len; i++) {
- byte b = data[i];
- check_sum += b;
- UART_SendByte(b);
- }
- UART_SendByte(check_sum);
+ byte check_sum = (0xFF + cmdType + (payload_len >> 8) + (payload_len & 0xFF));
+ UART_InitUART(g_baudRate);
+ UART_SendByte(0x55);
+ UART_SendByte(0xAA);
+ UART_SendByte(0x00); // version 00
+ UART_SendByte(cmdType); // version 00
+ UART_SendByte(payload_len >> 8); // following data length (Hi)
+ UART_SendByte(payload_len & 0xFF); // following data length (Lo)
+ for(i = 0; i < payload_len; i++) {
+ byte b = data[i];
+ check_sum += b;
+ UART_SendByte(b);
+ }
+ UART_SendByte(check_sum);
}
void TuyaMCU_SendState(uint8_t id, uint8_t type, uint8_t* value)
@@ -397,72 +408,72 @@ void TuyaMCU_SendRaw(uint8_t id, char data[]) {
}
void TuyaMCU_Send_SetTime(struct tm *pTime) {
- byte payload_buffer[8];
- byte tuya_day_of_week;
+ byte payload_buffer[8];
+ byte tuya_day_of_week;
- if (pTime->tm_wday == 1) {
- tuya_day_of_week = 7;
- } else {
- tuya_day_of_week = pTime->tm_wday-1;
- }
+ if (pTime->tm_wday == 1) {
+ tuya_day_of_week = 7;
+ } else {
+ tuya_day_of_week = pTime->tm_wday-1;
+ }
- payload_buffer[0] = 0x01;
- payload_buffer[1] = pTime->tm_year % 100;
- payload_buffer[2] = pTime->tm_mon;
- payload_buffer[3] = pTime->tm_mday;
- payload_buffer[4] = pTime->tm_hour;
- payload_buffer[5] = pTime->tm_min;
- payload_buffer[6] = pTime->tm_sec;
- payload_buffer[7] = tuya_day_of_week; //1 for Monday in TUYA Doc
+ payload_buffer[0] = 0x01;
+ payload_buffer[1] = pTime->tm_year % 100;
+ payload_buffer[2] = pTime->tm_mon;
+ payload_buffer[3] = pTime->tm_mday;
+ payload_buffer[4] = pTime->tm_hour;
+ payload_buffer[5] = pTime->tm_min;
+ payload_buffer[6] = pTime->tm_sec;
+ payload_buffer[7] = tuya_day_of_week; //1 for Monday in TUYA Doc
- TuyaMCU_SendCommandWithData(TUYA_CMD_SET_TIME, payload_buffer, 8);
+ TuyaMCU_SendCommandWithData(TUYA_CMD_SET_TIME, payload_buffer, 8);
}
struct tm * TuyaMCU_Get_NTP_Time() {
- int g_time;
- struct tm * ptm;
+ int g_time;
+ struct tm * ptm;
- g_time = NTP_GetCurrentTime();
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"MCU time to set: %i\n", g_time);
- ptm = gmtime(&g_time);
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"ptime ->gmtime => tm_hour: %i\n",ptm->tm_hour );
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"ptime ->gmtime => tm_min: %i\n", ptm->tm_min );
+ g_time = NTP_GetCurrentTime();
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"MCU time to set: %i\n", g_time);
+ ptm = gmtime(&g_time);
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"ptime ->gmtime => tm_hour: %i\n",ptm->tm_hour );
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"ptime ->gmtime => tm_min: %i\n", ptm->tm_min );
- return ptm;
+ return ptm;
}
//
int TuyaMCU_Fake_Hex(const void *context, const char *cmd, const char *args, int cmdFlags) {
- //const char *args = CMD_GetArg(1);
- //byte rawData[128];
- //int curCnt;
+ //const char *args = CMD_GetArg(1);
+ //byte rawData[128];
+ //int curCnt;
- //curCnt = 0;
- if(!(*args)) {
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_Fake_Hex: requires 1 argument (hex string, like FFAABB00CCDD\n");
- return -1;
- }
- while(*args) {
- byte b;
- b = hexbyte(args);
+ //curCnt = 0;
+ if(!(*args)) {
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_Fake_Hex: requires 1 argument (hex string, like FFAABB00CCDD\n");
+ return -1;
+ }
+ while(*args) {
+ byte b;
+ b = hexbyte(args);
- //rawData[curCnt] = b;
- //curCnt++;
- //if(curCnt>=sizeof(rawData)) {
- // addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_Fake_Hex: sorry, given string is too long\n");
- // return -1;
- //}
+ //rawData[curCnt] = b;
+ //curCnt++;
+ //if(curCnt>=sizeof(rawData)) {
+ // addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_Fake_Hex: sorry, given string is too long\n");
+ // return -1;
+ //}
- UART_AppendByteToCircularBuffer(b);
+ UART_AppendByteToCircularBuffer(b);
- args += 2;
- }
- return 1;
+ args += 2;
+ }
+ return 1;
}
void TuyaMCU_Send_RawBuffer(byte *data, int len) {
- int i;
+ int i;
- for(i = 0; i < len; i++) {
- UART_SendByte(data[i]);
- }
+ for(i = 0; i < len; i++) {
+ UART_SendByte(data[i]);
+ }
}
//battery-powered water sensor with TyuaMCU request to get somo response
// uartSendHex 55AA0001000000 - this will get reply:
@@ -483,155 +494,160 @@ Info:GEN:No change in channel 1 (still set to 0) - ignoring
*/
int TuyaMCU_Send_Hex(const void *context, const char *cmd, const char *args, int cmdFlags) {
- //const char *args = CMD_GetArg(1);
- if(!(*args)) {
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_Send_Hex: requires 1 argument (hex string, like FFAABB00CCDD\n");
- return -1;
- }
- while(*args) {
- byte b;
- b = hexbyte(args);
+ //const char *args = CMD_GetArg(1);
+ if(!(*args)) {
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_Send_Hex: requires 1 argument (hex string, like FFAABB00CCDD\n");
+ return -1;
+ }
+ while(*args) {
+ byte b;
+ b = hexbyte(args);
- UART_SendByte(b);
+ UART_SendByte(b);
- args += 2;
- }
- return 1;
+ args += 2;
+ }
+ return 1;
}
int TuyaMCU_LinkTuyaMCUOutputToChannel(const void *context, const char *cmd, const char *args, int cmdFlags) {
- int dpId;
- const char *dpTypeString;
- int dpType;
- int channelID;
+ int dpId;
+ const char *dpTypeString;
+ int dpType;
+ int channelID;
- // linkTuyaMCUOutputToChannel dpId varType channelID
- // linkTuyaMCUOutputToChannel 1 val 1
- Tokenizer_TokenizeString(args);
+ // linkTuyaMCUOutputToChannel dpId varType channelID
+ // linkTuyaMCUOutputToChannel 1 val 1
+ Tokenizer_TokenizeString(args);
- if(Tokenizer_GetArgsCount() < 3) {
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_LinkTuyaMCUOutputToChannel: requires 3 arguments (dpId, dpType, channelIndex)\n");
- return -1;
- }
- dpId = Tokenizer_GetArgInteger(0);
- dpTypeString = Tokenizer_GetArg(1);
- if(!stricmp(dpTypeString,"bool")) {
- dpType = DP_TYPE_BOOL;
- } else if(!stricmp(dpTypeString,"val")) {
- dpType = DP_TYPE_VALUE;
- } else if(!stricmp(dpTypeString,"str")) {
- dpType = DP_TYPE_STRING;
- } else if(!stricmp(dpTypeString,"enum")) {
- dpType = DP_TYPE_ENUM;
- } else if(!stricmp(dpTypeString,"raw")) {
- dpType = DP_TYPE_RAW;
- } else {
- if(strIsInteger(dpTypeString)) {
- dpType = atoi(dpTypeString);
- } else {
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_LinkTuyaMCUOutputToChannel: %s is not a valid var type\n",dpTypeString);
- return -1;
- }
- }
- channelID = Tokenizer_GetArgInteger(2);
+ if(Tokenizer_GetArgsCount() < 3) {
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_LinkTuyaMCUOutputToChannel: requires 3 arguments (dpId, dpType, channelIndex)\n");
+ return -1;
+ }
+ dpId = Tokenizer_GetArgInteger(0);
+ dpTypeString = Tokenizer_GetArg(1);
+ if(!stricmp(dpTypeString,"bool")) {
+ dpType = DP_TYPE_BOOL;
+ } else if(!stricmp(dpTypeString,"val")) {
+ dpType = DP_TYPE_VALUE;
+ } else if(!stricmp(dpTypeString,"str")) {
+ dpType = DP_TYPE_STRING;
+ } else if(!stricmp(dpTypeString,"enum")) {
+ dpType = DP_TYPE_ENUM;
+ } else if(!stricmp(dpTypeString,"raw")) {
+ dpType = DP_TYPE_RAW;
+ } else {
+ if(strIsInteger(dpTypeString)) {
+ dpType = atoi(dpTypeString);
+ } else {
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_LinkTuyaMCUOutputToChannel: %s is not a valid var type\n",dpTypeString);
+ return -1;
+ }
+ }
+ channelID = Tokenizer_GetArgInteger(2);
- TuyaMCU_MapIDToChannel(dpId, dpType, channelID);
+ TuyaMCU_MapIDToChannel(dpId, dpType, channelID);
- return 1;
+ return 1;
}
int TuyaMCU_Send_SetTime_Current(const void *context, const char *cmd, const char *args, int cmdFlags) {
- TuyaMCU_Send_SetTime(TuyaMCU_Get_NTP_Time());
+ TuyaMCU_Send_SetTime(TuyaMCU_Get_NTP_Time());
- return 1;
+ return 1;
}
int TuyaMCU_Send_SetTime_Example(const void *context, const char *cmd, const char *args, int cmdFlags) {
- struct tm testTime;
+ struct tm testTime;
- testTime.tm_year = 2012;
- testTime.tm_mon = 7;
- testTime.tm_mday = 15;
- testTime.tm_wday = 4;
- testTime.tm_hour = 6;
- testTime.tm_min = 54;
- testTime.tm_sec = 32;
+ testTime.tm_year = 2012;
+ testTime.tm_mon = 7;
+ testTime.tm_mday = 15;
+ testTime.tm_wday = 4;
+ testTime.tm_hour = 6;
+ testTime.tm_min = 54;
+ testTime.tm_sec = 32;
- TuyaMCU_Send_SetTime(&testTime);
- return 1;
+ TuyaMCU_Send_SetTime(&testTime);
+ return 1;
}
void TuyaMCU_Send(byte *data, int size) {
- int i;
+ int i;
unsigned char check_sum;
- check_sum = 0;
- for(i = 0; i < size; i++) {
- byte b = data[i];
- check_sum += b;
- UART_SendByte(b);
- }
- UART_SendByte(check_sum);
+ check_sum = 0;
+ for(i = 0; i < size; i++) {
+ byte b = data[i];
+ check_sum += b;
+ UART_SendByte(b);
+ }
+ UART_SendByte(check_sum);
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"\nWe sent %i bytes to Tuya MCU\n",size+1);
+ 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, int cmdFlags) {
- Tokenizer_TokenizeString(args);
+ Tokenizer_TokenizeString(args);
- if(Tokenizer_GetArgsCount() < 2) {
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"tuyaMcu_setDimmerRange: requires 2 arguments (dimmerRangeMin, dimmerRangeMax)\n");
- return -1;
- }
+ 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);
+ g_dimmerRangeMin = Tokenizer_GetArgInteger(0);
+ g_dimmerRangeMax = Tokenizer_GetArgInteger(1);
- return 1;
+ return 1;
}
int TuyaMCU_SendHeartbeat(const void *context, const char *cmd, const char *args, int cmdFlags) {
- TuyaMCU_SendCommandWithData(TUYA_CMD_HEARTBEAT, NULL, 0);
+ TuyaMCU_SendCommandWithData(TUYA_CMD_HEARTBEAT, NULL, 0);
- return 1;
+ return 1;
}
int TuyaMCU_SendQueryProductInformation(const void *context, const char *cmd, const char *args, int cmdFlags) {
- TuyaMCU_SendCommandWithData(TUYA_CMD_QUERY_PRODUCT, NULL, 0);
+ TuyaMCU_SendCommandWithData(TUYA_CMD_QUERY_PRODUCT, NULL, 0);
- return 1;
+ return 1;
}
int TuyaMCU_SendQueryState(const void *context, const char *cmd, const char *args, int cmdFlags) {
- TuyaMCU_SendCommandWithData(TUYA_CMD_QUERY_STATE, NULL, 0);
+ TuyaMCU_SendCommandWithData(TUYA_CMD_QUERY_STATE, NULL, 0);
- return 1;
+ return 1;
}
int TuyaMCU_SendStateCmd(const void *context, const char *cmd, const char *args, int cmdFlags) {
- int dpId;
- int dpType;
- int value;
+ int dpId;
+ int dpType;
+ int value;
- Tokenizer_TokenizeString(args);
+ Tokenizer_TokenizeString(args);
- if(Tokenizer_GetArgsCount() < 3) {
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"tuyaMcu_sendState: requires 3 arguments (dpId, dpType, value)\n");
- return -1;
- }
+ 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);
+ dpId = Tokenizer_GetArgInteger(0);
+ dpType = Tokenizer_GetArgInteger(1);
+ value = Tokenizer_GetArgInteger(2);
- TuyaMCU_SendState(dpId, dpType, (uint8_t *)&value);
+ TuyaMCU_SendState(dpId, dpType, (uint8_t *)&value);
- return 1;
+ return 1;
}
int TuyaMCU_SendMCUConf(const void *context, const char *cmd, const char *args, int cmdFlags) {
- TuyaMCU_SendCommandWithData(TUYA_CMD_MCU_CONF, NULL, 0);
+ TuyaMCU_SendCommandWithData(TUYA_CMD_MCU_CONF, NULL, 0);
- return 1;
+ return 1;
+}
+
+void Tuya_SetWifiState(uint8_t state)
+{
+ TuyaMCU_SendCommandWithData(TUYA_CMD_WIFI_STATE, &state, 1);
}
// ntp_timeZoneOfs 2
@@ -646,109 +662,109 @@ int TuyaMCU_SendMCUConf(const void *context, const char *cmd, const char *args,
// backlog ntp_timeZoneOfs 2; addRepeatingEvent 10 -1 uartSendHex 55AA0008000007; setChannelType 1 temperature_div10; setChannelType 2 humidity; linkTuyaMCUOutputToChannel 1 1; linkTuyaMCUOutputToChannel 2 2; addRepeatingEvent 10 -1 tuyaMcu_sendCurTime
//
void TuyaMCU_ApplyMapping(int fnID, int value) {
- tuyaMCUMapping_t *mapping;
- int mappedValue = value;
+ tuyaMCUMapping_t *mapping;
+ int mappedValue = value;
- // find mapping (where to save received data)
- mapping = TuyaMCU_FindDefForID(fnID);
+ // find mapping (where to save received data)
+ mapping = TuyaMCU_FindDefForID(fnID);
- if(mapping == 0){
- addLogAdv(LOG_DEBUG, LOG_FEATURE_TUYAMCU,"TuyaMCU_ApplyMapping: id %i with value %i is not mapped\n", fnID, value);
- return;
- }
+ if(mapping == 0){
+ addLogAdv(LOG_DEBUG, LOG_FEATURE_TUYAMCU,"TuyaMCU_ApplyMapping: id %i with value %i is not mapped\n", fnID, value);
+ return;
+ }
- // 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;
- case ChType_Dimmer256:
- // map TuyaMCU's dimmer range to OpenBK7231T_App's dimmer range 0..256
- mappedValue = ((value - g_dimmerRangeMin) * 256) / (g_dimmerRangeMax - g_dimmerRangeMin);
- break;
- default:
- break;
- }
+ // 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;
+ case ChType_Dimmer256:
+ // map TuyaMCU's dimmer range to OpenBK7231T_App's dimmer range 0..256
+ mappedValue = ((value - g_dimmerRangeMin) * 256) / (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);
- }
+ if (value != mappedValue) {
+ addLogAdv(LOG_DEBUG, LOG_FEATURE_TUYAMCU,"TuyaMCU_ApplyMapping: mapped value %d (TuyaMCU range) to %d (OpenBK7321T_App range)\n", value, mappedValue);
+ }
- mapping->prevValue = mappedValue;
+ mapping->prevValue = mappedValue;
- CHANNEL_Set(mapping->channel,mappedValue,0);
+ CHANNEL_Set(mapping->channel,mappedValue,0);
}
void TuyaMCU_OnChannelChanged(int channel, int iVal) {
- tuyaMCUMapping_t *mapping;
- int mappediVal = iVal;
+ tuyaMCUMapping_t *mapping;
+ int mappediVal = iVal;
- // find mapping
- mapping = TuyaMCU_FindDefForChannel(channel);
+ // find mapping
+ mapping = TuyaMCU_FindDefForChannel(channel);
- if(mapping == 0){
- return;
- }
+ if(mapping == 0){
+ 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;
- }
+ // 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))
- {
- 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;
- case ChType_Dimmer256:
- // map OpenBK7231T_App's dimmer range 0..256 to TuyaMCU's dimmer range
- mappediVal = (((g_dimmerRangeMax - g_dimmerRangeMin) * iVal) / 256) + g_dimmerRangeMin;
- break;
- default:
- break;
- }
+ // 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;
+ case ChType_Dimmer256:
+ // map OpenBK7231T_App's dimmer range 0..256 to TuyaMCU's dimmer range
+ mappediVal = (((g_dimmerRangeMax - g_dimmerRangeMin) * iVal) / 256) + 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);
- }
+ 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;
+ // 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_ENUM:
+ TuyaMCU_SendEnum(mapping->fnId, mappediVal);
+ break;
- case DP_TYPE_VALUE:
- TuyaMCU_SendValue(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;
- }
+ 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_ParseQueryProductInformation(const byte *data, int len) {
- char name[256];
- int useLen;
+ char name[256];
+ int useLen;
- useLen = len-1;
- if(useLen > sizeof(name)-1)
- useLen = sizeof(name)-1;
- memcpy(name,data,useLen);
- name[useLen] = 0;
+ useLen = len-1;
+ if(useLen > sizeof(name)-1)
+ useLen = sizeof(name)-1;
+ memcpy(name,data,useLen);
+ name[useLen] = 0;
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ParseQueryProductInformation: received %s\n", name);
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ParseQueryProductInformation: received %s\n", name);
}
// Protocol version - 0x00 (not 0x03)
// Used for battery powered devices, eg. door sensor.
@@ -756,188 +772,210 @@ void TuyaMCU_ParseQueryProductInformation(const byte *data, int len) {
//55AA 00 08 000C 00 02 02 02 02 02 02 01 01 00 01 01 23
-//Head v0 ID lengh bV YY MM DD HH MM SS CHKSUM
+//Head v0 ID lengh bV YY MM DD HH MM SS CHKSUM
// after that, there are status data uniys
-// 01 01 0001 01
-// dpId Type Len Value
+// 01 01 0001 01
+// dpId Type Len Value
void TuyaMCU_V0_ParseRealTimeWithRecordStorage(const byte *data, int len) {
- int ofs;
- int sectorLen;
- int fnId;
- int dataType;
+ int ofs;
+ int sectorLen;
+ int fnId;
+ int dataType;
- //data[0]; // bDateValid
- //data[1]; // year
- //data[2]; // month
- //data[3]; // day
- //data[4]; // hour
- //data[5]; // minute
- //data[6]; // second
+ //data[0]; // bDateValid
+ //data[1]; // year
+ //data[2]; // month
+ //data[3]; // day
+ //data[4]; // hour
+ //data[5]; // minute
+ //data[6]; // second
- ofs = 7;
+ ofs = 7;
- while(ofs + 4 < len) {
- sectorLen = data[ofs + 2] << 8 | data[ofs + 3];
- fnId = data[ofs];
- dataType = data[ofs+1];
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_V0_ParseRealTimeWithRecordStorage: processing dpId %i, dataType %i-%s and %i data bytes\n",
- fnId, dataType, TuyaMCU_GetDataTypeString(dataType),sectorLen);
+ while(ofs + 4 < len) {
+ sectorLen = data[ofs + 2] << 8 | data[ofs + 3];
+ fnId = data[ofs];
+ dataType = data[ofs+1];
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_V0_ParseRealTimeWithRecordStorage: processing dpId %i, dataType %i-%s and %i data bytes\n",
+ fnId, dataType, TuyaMCU_GetDataTypeString(dataType),sectorLen);
- if(sectorLen == 1) {
- int iVal = (int)data[ofs+4];
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_V0_ParseRealTimeWithRecordStorage: raw data 1 byte: %c\n",iVal);
- // apply to channels
- TuyaMCU_ApplyMapping(fnId,iVal);
- }
- if(sectorLen == 4) {
- int iVal = data[ofs + 4] << 24 | data[ofs + 5] << 16 | data[ofs + 6] << 8 | data[ofs + 7];
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_V0_ParseRealTimeWithRecordStorage: raw data 4 int: %i\n",iVal);
- // apply to channels
- TuyaMCU_ApplyMapping(fnId,iVal);
- }
+ if(sectorLen == 1) {
+ int iVal = (int)data[ofs+4];
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_V0_ParseRealTimeWithRecordStorage: raw data 1 byte: %c\n",iVal);
+ // apply to channels
+ TuyaMCU_ApplyMapping(fnId,iVal);
+ }
+ if(sectorLen == 4) {
+ int iVal = data[ofs + 4] << 24 | data[ofs + 5] << 16 | data[ofs + 6] << 8 | data[ofs + 7];
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_V0_ParseRealTimeWithRecordStorage: raw data 4 int: %i\n",iVal);
+ // apply to channels
+ TuyaMCU_ApplyMapping(fnId,iVal);
+ }
- // size of header (type, datatype, len 2 bytes) + data sector size
- ofs += (4+sectorLen);
- }
+ // size of header (type, datatype, len 2 bytes) + data sector size
+ ofs += (4+sectorLen);
+ }
}
void TuyaMCU_ParseStateMessage(const byte *data, int len) {
- int ofs;
- int sectorLen;
- int fnId;
- int dataType;
+ int ofs;
+ int sectorLen;
+ int fnId;
+ int dataType;
- ofs = 0;
+ ofs = 0;
- while(ofs + 4 < 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 dpId %i, dataType %i-%s and %i data bytes\n",
- fnId, dataType, TuyaMCU_GetDataTypeString(dataType),sectorLen);
+ while(ofs + 4 < 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 dpId %i, dataType %i-%s and %i data bytes\n",
+ fnId, dataType, TuyaMCU_GetDataTypeString(dataType),sectorLen);
- if(sectorLen == 1) {
- int iVal = (int)data[ofs+4];
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ParseStateMessage: raw data 1 byte: %c\n",iVal);
- // apply to channels
- TuyaMCU_ApplyMapping(fnId,iVal);
- }
- if(sectorLen == 4) {
- int iVal = data[ofs + 4] << 24 | data[ofs + 5] << 16 | data[ofs + 6] << 8 | data[ofs + 7];
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ParseStateMessage: raw data 4 int: %i\n",iVal);
- // apply to channels
- TuyaMCU_ApplyMapping(fnId,iVal);
- }
+ if(sectorLen == 1) {
+ int iVal = (int)data[ofs+4];
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ParseStateMessage: raw data 1 byte: %c\n",iVal);
+ // apply to channels
+ TuyaMCU_ApplyMapping(fnId,iVal);
+ }
+ if(sectorLen == 4) {
+ int iVal = data[ofs + 4] << 24 | data[ofs + 5] << 16 | data[ofs + 6] << 8 | data[ofs + 7];
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ParseStateMessage: raw data 4 int: %i\n",iVal);
+ // apply to channels
+ TuyaMCU_ApplyMapping(fnId,iVal);
+ }
- // size of header (type, datatype, len 2 bytes) + data sector size
- ofs += (4+sectorLen);
- }
+ // size of header (type, datatype, len 2 bytes) + data sector size
+ ofs += (4+sectorLen);
+ }
}
-#define TUYA_V0_CMD_PRODUCTINFORMATION 0x01
-#define TUYA_V0_CMD_NETWEORKSTATUS 0x02
-#define TUYA_V0_CMD_RESETWIFI 0x03
-#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_PRODUCTINFORMATION 0x01
+#define TUYA_V0_CMD_NETWEORKSTATUS 0x02
+#define TUYA_V0_CMD_RESETWIFI 0x03
+#define TUYA_V0_CMD_RESETWIFI_AND_SEL_CONF 0x04
+#define TUYA_V0_CMD_REALTIMESTATUS 0x05
+#define TUYA_V0_CMD_RECORDSTATUS 0x08
void TuyaMCU_ProcessIncoming(const byte *data, int len) {
- int checkLen;
- int i;
- byte checkCheckSum;
- byte cmd;
- byte version;
+ int checkLen;
+ int i;
+ byte checkCheckSum;
+ byte cmd;
+ byte version;
- if(data[0] != 0x55 || data[1] != 0xAA) {
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming: discarding packet with bad ident and len %i\n",len);
- return;
- }
- version = data[2];
- checkLen = data[5] | data[4] >> 8;
- checkLen = checkLen + 2 + 1 + 1 + 2 + 1;
- if(checkLen != len) {
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming: discarding packet bad expected len, expected %i and got len %i\n",checkLen,len);
- return;
- }
- checkCheckSum = 0;
- for(i = 0; i < len-1; i++) {
- checkCheckSum += data[i];
- }
- if(checkCheckSum != data[len-1]) {
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming: discarding packet bad expected checksum, expected %i and got checksum %i\n",(int)data[len-1],(int)checkCheckSum);
- return;
- }
- cmd = data[3];
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming[ver=%i]: processing command %i (%s) with %i bytes\n",version,cmd,TuyaMCU_GetCommandTypeLabel(cmd),len);
- switch(cmd)
- {
- case TUYA_CMD_STATE:
- TuyaMCU_ParseStateMessage(data+6,len-6);
- break;
- case TUYA_CMD_SET_TIME:
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming: received TUYA_CMD_SET_TIME, so sending back time");
- TuyaMCU_Send_SetTime(TuyaMCU_Get_NTP_Time());
- break;
- // 55 AA 00 01 00 ${"p":"e7dny8zvmiyhqerw","v":"1.0.0"}$
- // tuyaMcu_fakeHex 55AA000100247B2270223A226537646E79387A766D69796871657277222C2276223A22312E302E30227D24
- case TUYA_CMD_QUERY_PRODUCT:
- TuyaMCU_ParseQueryProductInformation(data+6,len-6);
- break;
- // this name seems invalid for Version 0 of TuyaMCU
- case TUYA_CMD_QUERY_STATE:
- if(version == 0) {
- // 0x08 packet for version 0 (not 0x03) of TuyaMCU
- TuyaMCU_V0_ParseRealTimeWithRecordStorage(data+6,len-6);
- } else {
+ if(data[0] != 0x55 || data[1] != 0xAA) {
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming: discarding packet with bad ident and len %i\n",len);
+ return;
+ }
+ version = data[2];
+ checkLen = data[5] | data[4] >> 8;
+ checkLen = checkLen + 2 + 1 + 1 + 2 + 1;
+ if(checkLen != len) {
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming: discarding packet bad expected len, expected %i and got len %i\n",checkLen,len);
+ return;
+ }
+ checkCheckSum = 0;
+ for(i = 0; i < len-1; i++) {
+ checkCheckSum += data[i];
+ }
+ if(checkCheckSum != data[len-1]) {
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming: discarding packet bad expected checksum, expected %i and got checksum %i\n",(int)data[len-1],(int)checkCheckSum);
+ return;
+ }
+ cmd = data[3];
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming[ver=%i]: processing command %i (%s) with %i bytes\n",version,cmd,TuyaMCU_GetCommandTypeLabel(cmd),len);
+ switch(cmd)
+ {
+ case TUYA_CMD_HEARTBEAT:
+ heartbeat_valid = true;
+ heartbeat_counter = 0;
+ break;
+ case TUYA_CMD_MCU_CONF:
+ working_mode_valid = true;
+ if (checkLen == 0)
+ {
+ self_processing_mode = true;
+ }
+ else if (checkLen == 2)
+ {
+ self_processing_mode = false;
+ }
+ break;
+ case TUYA_CMD_WIFI_STATE:
+ wifi_state_valid = true;
+ break;
- }
- break;
- default:
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming: unhandled type %i",cmd);
- break;
- }
+ case TUYA_CMD_STATE:
+ TuyaMCU_ParseStateMessage(data+6,len-6);
+ state_updated = true;
+ break;
+ case TUYA_CMD_SET_TIME:
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming: received TUYA_CMD_SET_TIME, so sending back time");
+ TuyaMCU_Send_SetTime(TuyaMCU_Get_NTP_Time());
+ break;
+ // 55 AA 00 01 00 ${"p":"e7dny8zvmiyhqerw","v":"1.0.0"}$
+ // tuyaMcu_fakeHex 55AA000100247B2270223A226537646E79387A766D69796871657277222C2276223A22312E302E30227D24
+ case TUYA_CMD_QUERY_PRODUCT:
+ TuyaMCU_ParseQueryProductInformation(data+6,len-6);
+ product_information_valid = true;
+ break;
+ // this name seems invalid for Version 0 of TuyaMCU
+ case TUYA_CMD_QUERY_STATE:
+ if(version == 0) {
+ // 0x08 packet for version 0 (not 0x03) of TuyaMCU
+ TuyaMCU_V0_ParseRealTimeWithRecordStorage(data+6,len-6);
+ } else {
+
+ }
+ break;
+ default:
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming: unhandled type %i",cmd);
+ break;
+ }
}
-int TuyaMCU_FakePacket(const void *context, const char *cmd, const char *args, int cmdFlags) {
- byte packet[256];
- int c = 0;
- if(!(*args)) {
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_FakePacket: requires 1 argument (hex string, like FFAABB00CCDD\n");
- return -1;
- }
- while(*args) {
- byte b;
- b = hexbyte(args);
- if(sizeof(packet)>c+1) {
- packet[c] = b;
- c++;
- }
- args += 2;
- }
- TuyaMCU_ProcessIncoming(packet,c);
- return 1;
+int TuyaMCU_FakePacket(const void *context, const char *cmd, const char *args, int cmdFlags) {
+ byte packet[256];
+ int c = 0;
+ if(!(*args)) {
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_FakePacket: requires 1 argument (hex string, like FFAABB00CCDD\n");
+ return -1;
+ }
+ while(*args) {
+ byte b;
+ b = hexbyte(args);
+
+ if(sizeof(packet)>c+1) {
+ packet[c] = b;
+ c++;
+ }
+ args += 2;
+ }
+ TuyaMCU_ProcessIncoming(packet,c);
+ return 1;
}
void TuyaMCU_RunFrame() {
- byte data[128];
- char buffer_for_log[256];
- char buffer2[4];
- int len, i;
+ byte data[128];
+ char buffer_for_log[256];
+ char buffer2[4];
+ int len, i;
- //addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"UART ring buffer state: %i %i\n",g_recvBufIn,g_recvBufOut);
+ //addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"UART ring buffer state: %i %i\n",g_recvBufIn,g_recvBufOut);
while (1)
{
- len = UART_TryToGetNextTuyaPacket(data,sizeof(data));
- if(len > 0) {
- buffer_for_log[0] = 0;
- for(i = 0; i < len; i++) {
- sprintf(buffer2,"%02X ",data[i]);
- strcat_safe(buffer_for_log,buffer2,sizeof(buffer_for_log));
- }
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TUYAMCU received: %s\n", buffer_for_log);
- TuyaMCU_ProcessIncoming(data,len);
- } else {
+ len = UART_TryToGetNextTuyaPacket(data,sizeof(data));
+ if(len > 0) {
+ buffer_for_log[0] = 0;
+ for(i = 0; i < len; i++) {
+ sprintf(buffer2,"%02X ",data[i]);
+ strcat_safe(buffer_for_log,buffer2,sizeof(buffer_for_log));
+ }
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TUYAMCU received: %s\n", buffer_for_log);
+ TuyaMCU_ProcessIncoming(data,len);
+ } else {
break;
}
}
@@ -1005,38 +1043,38 @@ void TuyaMCU_RunFrame() {
int TuyaMCU_SetBaudRate(const void *context, const char *cmd, const char *args, int cmdFlags) {
- Tokenizer_TokenizeString(args);
+ Tokenizer_TokenizeString(args);
- if(Tokenizer_GetArgsCount() < 1) {
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_SetBaudRate: requires 1 arguments (baudRate)\n");
- return -1;
- }
+ if(Tokenizer_GetArgsCount() < 1) {
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_SetBaudRate: requires 1 arguments (baudRate)\n");
+ return -1;
+ }
- g_baudRate = Tokenizer_GetArgInteger(0);
-
- return 1;
+ g_baudRate = Tokenizer_GetArgInteger(0);
+
+ return 1;
}
void TuyaMCU_Init()
{
- UART_InitUART(g_baudRate);
- UART_InitReceiveRingBuffer(256);
- // uartSendHex 55AA0008000007
- CMD_RegisterCommand("tuyaMcu_testSendTime","",TuyaMCU_Send_SetTime_Example, "Sends a example date by TuyaMCU to clock/callendar MCU", NULL);
- CMD_RegisterCommand("tuyaMcu_sendCurTime","",TuyaMCU_Send_SetTime_Current, "Sends a current date by TuyaMCU to clock/callendar MCU", NULL);
- CMD_RegisterCommand("uartSendHex","",TuyaMCU_Send_Hex, "Sends raw data by TuyaMCU UART, you must write whole packet with checksum yourself", NULL);
- CMD_RegisterCommand("tuyaMcu_fakeHex","",TuyaMCU_Fake_Hex, "qq", 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_sendProductInformation","",TuyaMCU_SendQueryProductInformation, "Send qqq", NULL);
- CMD_RegisterCommand("tuyaMcu_sendState","",TuyaMCU_SendStateCmd, "Send set state command", NULL);
- CMD_RegisterCommand("tuyaMcu_sendMCUConf","",TuyaMCU_SendMCUConf, "Send MCU conf command", NULL);
- CMD_RegisterCommand("fakeTuyaPacket","",TuyaMCU_FakePacket, "qq", NULL);
- CMD_RegisterCommand("tuyaMcu_setBaudRate","",TuyaMCU_SetBaudRate, "Set the serial baud rate used to communicate with the TuyaMCU", NULL);
+ UART_InitUART(g_baudRate);
+ UART_InitReceiveRingBuffer(256);
+ // uartSendHex 55AA0008000007
+ CMD_RegisterCommand("tuyaMcu_testSendTime","",TuyaMCU_Send_SetTime_Example, "Sends a example date by TuyaMCU to clock/callendar MCU", NULL);
+ CMD_RegisterCommand("tuyaMcu_sendCurTime","",TuyaMCU_Send_SetTime_Current, "Sends a current date by TuyaMCU to clock/callendar MCU", NULL);
+ CMD_RegisterCommand("uartSendHex","",TuyaMCU_Send_Hex, "Sends raw data by TuyaMCU UART, you must write whole packet with checksum yourself", NULL);
+ CMD_RegisterCommand("tuyaMcu_fakeHex","",TuyaMCU_Fake_Hex, "qq", 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_sendProductInformation","",TuyaMCU_SendQueryProductInformation, "Send qqq", NULL);
+ CMD_RegisterCommand("tuyaMcu_sendState","",TuyaMCU_SendStateCmd, "Send set state command", NULL);
+ CMD_RegisterCommand("tuyaMcu_sendMCUConf","",TuyaMCU_SendMCUConf, "Send MCU conf command", NULL);
+ CMD_RegisterCommand("fakeTuyaPacket","",TuyaMCU_FakePacket, "qq", NULL);
+ CMD_RegisterCommand("tuyaMcu_setBaudRate","",TuyaMCU_SetBaudRate, "Set the serial baud rate used to communicate with the TuyaMCU", NULL);
}
// Door sensor with TuyaMCU version 0 (not 3), so all replies have x00 and not 0x03 byte
// fakeTuyaPacket 55AA0008000C00010101010101030400010223
@@ -1048,7 +1086,7 @@ void TuyaMCU_Init()
/// 55AA 00 08 000C 00 02 02 02 02 02 02 01 01 0001 01 23
/// head vr id size FL YY MM DD HH MM SS ID TP SIZE VL CK
/// 55AA 00 08 000C 00 01 01 01 01 01 01 03 04 0001 02 23
-// TP = 0x01 bool 1 Value range: 0x00/0x01.
-// TP = 0x04 enum 1 Enumeration type, ranging from 0 to 255.
+// TP = 0x01 bool 1 Value range: 0x00/0x01.
+// TP = 0x04 enum 1 Enumeration type, ranging from 0 to 255.
diff --git a/src/httpserver/hass.c b/src/httpserver/hass.c
index d1b77d5ea..b655b457c 100644
--- a/src/httpserver/hass.c
+++ b/src/httpserver/hass.c
@@ -134,7 +134,10 @@ HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, char* payload
break;
case ENTITY_SENSOR:
#ifndef OBK_DISABLE_ALL_DRIVERS
- sprintf(g_hassBuffer, "%s %s", CFG_GetShortDeviceName(), sensor_mqttNames[index]);
+ if ((index >= OBK_VOLTAGE) && (index <= OBK_POWER))
+ sprintf(g_hassBuffer, "%s %s", CFG_GetShortDeviceName(), sensor_mqttNames[index]);
+ if ((index >= OBK_CONSUMPTION_TOTAL) && (index <= OBK_CONSUMPTION_STATS))
+ sprintf(g_hassBuffer, "%s %s", CFG_GetShortDeviceName(), counter_mqttNames[index - OBK_CONSUMPTION_TOTAL]);
#endif
break;
}
@@ -231,10 +234,20 @@ HassDeviceInfo* hass_init_light_device_info(ENTITY_TYPE type, int index) {
//https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes
//device_class automatically assigns unit,icon
- cJSON_AddStringToObject(info->root, "dev_cla", sensor_mqttNames[index]); //device_class=voltage,current,power
+ if ((index >= OBK_VOLTAGE) && (index <= OBK_POWER))
+ {
+ cJSON_AddStringToObject(info->root, "dev_cla", sensor_mqttNames[index]); //device_class=voltage,current,power
- sprintf(g_hassBuffer, "%s/%s/get", clientId, sensor_mqttNames[index]);
- cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer);
+ sprintf(g_hassBuffer, "%s/%s/get", clientId, sensor_mqttNames[index]);
+ cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer);
+ }
+ if ((index >= OBK_CONSUMPTION_TOTAL) && (index <= OBK_CONSUMPTION_STATS))
+ {
+ cJSON_AddStringToObject(info->root, "dev_cla", counter_mqttNames[index - OBK_CONSUMPTION_TOTAL]); //device_class=consumption
+
+ sprintf(g_hassBuffer, "%s/%s/get", clientId, counter_mqttNames[index - OBK_CONSUMPTION_TOTAL]);
+ cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer);
+ }
#endif
break;
diff --git a/src/httpserver/http_fns.c b/src/httpserver/http_fns.c
index 23b2779a5..cad02feca 100644
--- a/src/httpserver/http_fns.c
+++ b/src/httpserver/http_fns.c
@@ -92,8 +92,9 @@ template_t g_templates[] = {
{ Setup_Device_Enbrighten_WFD4103, "Enbrighten WFD4103 WiFi Switch BK7231T WB2S"} ,
{ Setup_Device_Zemismart_Light_Switch_KS_811_3, "Zemismart Light Switch (Neutral Optional) KS_811_3"} ,
{ Setup_Device_TeslaSmartPlus_TSL_SPL_1, "Tesla Smart Plug. Model: (TSL-SPL-1)"},
- { Setup_Device_Calex_900011_1_WB2S, "Calex Smart Power Plug 900011.1"}
-
+ { Setup_Device_Calex_900011_1_WB2S, "Calex Smart Power Plug 900011.1"},
+ { Setup_Device_Immax_NEO_LITE_NAS_WR07W, "Immax NEO Lite. Model: (NAS-WR07W)"} ,
+ { Setup_Device_MOES_TouchSwitch_WS_EU1_RFW_N, "MOES Touch Switch 1gang Model:(WS-EU1-RFW-N)"}
};
int g_total_templates = sizeof(g_templates) / sizeof(g_templates[0]);
@@ -548,6 +549,34 @@ int http_fn_index(http_request_t* request) {
hprintf128(request, "MQTT Stats:CONN: %d PUB: %d RECV: %d ERR: %d ", MQTT_GetConnectEvents(),
MQTT_GetPublishEventCounter(), MQTT_GetReceivedEventCounter(), MQTT_GetPublishErrorCounter());
+ /* Format current PINS input state for all unused pins */
+ if(CFG_HasFlag(OBK_FLAG_HTTP_PINMONITOR))
+ {
+ for (i=0;i<29;i++)
+ {
+ if ((PIN_GetPinRoleForPinIndex(i) == IOR_None) && (i!=10) && (i!=11))
+ {
+ HAL_PIN_Setup_Input(i);
+ }
+ }
+
+ hprintf128(request," PIN States
");
+ for (i=0;i<29;i++)
+ {
+ if ((PIN_GetPinRoleForPinIndex(i) != IOR_None) || (i==10) || (i==11))
+ {
+ hprintf128(request,"P%02i: NA ", i);
+ } else {
+ hprintf128(request,"P%02i: %i ", i, (int)HAL_PIN_ReadDigitalInput(i));
+ }
+ if (i%10==9)
+ {
+ hprintf128(request,"
");
+ }
+ }
+ hprintf128(request,"
");
+ }
+
// for normal page loads, show the rest of the HTML
if (!http_getArg(request->url, "state", tmpA, sizeof(tmpA))) {
poststr(request, ""); // end div#state
@@ -1280,7 +1309,7 @@ int http_fn_ha_discovery(http_request_t* request) {
#ifndef OBK_DISABLE_ALL_DRIVERS
if (DRV_IsMeasuringPower()) {
- for (i = 0;i < OBK_NUM_MEASUREMENTS;i++)
+ for (i = 0;i < OBK_NUM_SENSOR_COUNT;i++)
{
HassDeviceInfo* dev_info = hass_init_light_device_info(ENTITY_SENSOR, i);
MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN);
@@ -1500,24 +1529,32 @@ int http_tasmota_json_power(http_request_t* request) {
*/
int http_tasmota_json_status_SNS(http_request_t* request) {
float power, factor, voltage, current;
+ float energy, energy_hour;
#ifndef OBK_DISABLE_ALL_DRIVERS
factor = 0; // TODO
voltage = DRV_GetReading(OBK_VOLTAGE);
current = DRV_GetReading(OBK_CURRENT);
power = DRV_GetReading(OBK_POWER);
+ energy = DRV_GetReading(OBK_CONSUMPTION_TOTAL);
+ energy_hour = DRV_GetReading(OBK_CONSUMPTION_LAST_HOUR);
+
#else
factor = 0;
voltage = 0;
current = 0;
power = 0;
+ energy = 0;
+ energy_hour = 0;
#endif
hprintf128(request, "{\"StatusSNS\":{\"ENERGY\":{");
hprintf128(request, "\"Power\": %f,", power);
hprintf128(request, "\"ApparentPower\": 0,\"ReactivePower\": 0,\"Factor\":%f,", factor);
hprintf128(request, "\"Voltage\":%f,", voltage);
- hprintf128(request, "\"Current\":%f}}}", current);
+ hprintf128(request, "\"Current\":%f,", current);
+ hprintf128(request, "\"ConsumptionTotal\":%f,", energy);
+ hprintf128(request, "\"ConsumptionLastHour\":%f}}}", energy_hour);
return 0;
}
@@ -1756,6 +1793,7 @@ const char* g_obk_flagNames[] = {
"[MQTT] Broadcast self state on MQTT connect",
"[PWM] BK7231 use 600hz instead of 1khz default",
"[LED] remember LED driver state (RGBCW, enable, brightness, temperature) after reboot",
+ "[HTTP] Show actual PIN logic level for unconfigured pins",
"error",
"error",
};
diff --git a/src/new_builtin_devices.c b/src/new_builtin_devices.c
index 3fc9ef3ff..0a9e2b9f0 100644
--- a/src/new_builtin_devices.c
+++ b/src/new_builtin_devices.c
@@ -910,6 +910,9 @@ void Setup_Device_TeslaSmartPlus_TSL_SPL_1() {
PIN_SetPinRoleForPinIndex(24, IOR_BL0937_SEL);
PIN_SetPinChannelForPinIndex(24, 0);
+ CFG_SetFlag(2,1);
+ CFG_SetFlag(10,1);
+
CFG_Save_SetupTimer();
}
@@ -930,3 +933,33 @@ void Setup_Device_Calex_900011_1_WB2S(){
CFG_Save_SetupTimer();
}
+void Setup_Device_Immax_NEO_LITE_NAS_WR07W()
+{
+ CFG_ClearPins();
+
+ // Button
+ PIN_SetPinRoleForPinIndex(9, IOR_Button_n);
+ PIN_SetPinChannelForPinIndex(9, 0);
+ // Relay
+ PIN_SetPinRoleForPinIndex(6, IOR_LED_WIFI_n);
+ PIN_SetPinChannelForPinIndex(6, 0);
+ // Led
+ PIN_SetPinRoleForPinIndex(26, IOR_Relay);
+ PIN_SetPinChannelForPinIndex(26, 0);
+
+ CFG_SetShortStartupCommand("backlog startDriver BL0942");
+ CFG_SetFlag(2,1);
+ CFG_SetFlag(10,1);
+
+ CFG_Save_SetupTimer();
+}
+
+void Setup_Device_MOES_TouchSwitch_WS_EU1_RFW_N()
+{
+ CFG_ClearPins();
+ CFG_SetShortStartupCommand("backlog startDriver TuyaMCU; setChannelType 1 toggle; linkTuyaMCUOutputToChannel 1 bool 1");
+ CFG_SetFlag(2,1);
+ CFG_SetFlag(10,1);
+ CFG_Save_SetupTimer();
+}
+
diff --git a/src/new_pins.h b/src/new_pins.h
index 596ff9081..4686511a2 100644
--- a/src/new_pins.h
+++ b/src/new_pins.h
@@ -119,8 +119,9 @@ typedef struct pinsState_s {
#define OBK_FLAG_MQTT_BROADCASTSELFSTATEONCONNECT 10
#define OBK_FLAG_SLOW_PWM 11
#define OBK_FLAG_LED_REMEMBERLASTSTATE 12
+#define OBK_FLAG_HTTP_PINMONITOR 13
-#define OBK_TOTAL_FLAGS 13
+#define OBK_TOTAL_FLAGS 14
#define CGF_MQTT_CLIENT_ID_SIZE 64
@@ -271,5 +272,6 @@ void Setup_Device_Aubess_Mini_Smart_Switch_16A();
void Setup_Device_Zemismart_Light_Switch_KS_811_3();
void Setup_Device_TeslaSmartPlus_TSL_SPL_1();
void Setup_Device_Calex_900011_1_WB2S();
-
+void Setup_Device_Immax_NEO_LITE_NAS_WR07W();
+void Setup_Device_MOES_TouchSwitch_WS_EU1_RFW_N();
#endif