diff --git a/src/driver/drv_local.h b/src/driver/drv_local.h
index 6b95126e0..122a5acf2 100644
--- a/src/driver/drv_local.h
+++ b/src/driver/drv_local.h
@@ -67,6 +67,11 @@ void SHT3X_AppendInformationToHTTPIndexPage(http_request_t* request);
void SHT3X_OnEverySecond();
void SHT3X_StopDriver();
+void SGP_Init();
+void SGP_AppendInformationToHTTPIndexPage(http_request_t* request);
+void SGP_OnEverySecond();
+void SGP_StopDriver();
+
void Batt_Init();
void Batt_OnEverySecond();
void Batt_AppendInformationToHTTPIndexPage(http_request_t* request);
@@ -93,12 +98,12 @@ typedef struct softI2C_s {
void Soft_I2C_SetLow(uint8_t pin);
void Soft_I2C_SetHigh(uint8_t pin);
-bool Soft_I2C_PreInit(softI2C_t *i2c);
-bool Soft_I2C_WriteByte(softI2C_t *i2c, uint8_t value);
-bool Soft_I2C_Start(softI2C_t *i2c, uint8_t addr);
-void Soft_I2C_Stop(softI2C_t *i2c);
-uint8_t Soft_I2C_ReadByte(softI2C_t *i2c, bool nack);
-void Soft_I2C_ReadBytes(softI2C_t *i2c, uint8_t* buf, int numOfBytes);
+bool Soft_I2C_PreInit(softI2C_t* i2c);
+bool Soft_I2C_WriteByte(softI2C_t* i2c, uint8_t value);
+bool Soft_I2C_Start(softI2C_t* i2c, uint8_t addr);
+void Soft_I2C_Stop(softI2C_t* i2c);
+uint8_t Soft_I2C_ReadByte(softI2C_t* i2c, bool nack);
+void Soft_I2C_ReadBytes(softI2C_t* i2c, uint8_t* buf, int numOfBytes);
// Shared LED driver
commandResult_t CMD_LEDDriver_Map(const void* context, const char* cmd, const char* args, int flags);
diff --git a/src/driver/drv_main.c b/src/driver/drv_main.c
index b994308ca..5b5e7bed1 100644
--- a/src/driver/drv_main.c
+++ b/src/driver/drv_main.c
@@ -237,6 +237,12 @@ static driver_t g_drivers[] = {
//drvdetail:"descr":"Humidity/temperature sensor. See [SHT Sensor tutorial topic here](https://www.elektroda.com/rtvforum/topic3958369.html), also see [this sensor teardown](https://www.elektroda.com/rtvforum/topic3945688.html)",
//drvdetail:"requires":""}
{ "SHT3X", SHT3X_Init, SHT3X_OnEverySecond, SHT3X_AppendInformationToHTTPIndexPage, NULL, SHT3X_StopDriver, NULL, false },
+ //drvdetail:{"name":"SGP",
+ //drvdetail:"title":"TODO",
+ //drvdetail:"descr":"Air Quality sensor.",
+ //drvdetail:"requires":""}
+ { "SGP", SGP_Init, SGP_OnEverySecond, SGP_AppendInformationToHTTPIndexPage, NULL, SGP_StopDriver, NULL, false },
+
//drvdetail:{"name":"ShiftRegister",
//drvdetail:"title":"TODO",
//drvdetail:"descr":"ShiftRegisterShiftRegisterShiftRegisterShiftRegister",
@@ -506,7 +512,7 @@ bool DRV_IsMeasuringBattery() {
bool DRV_IsSensor() {
#ifndef OBK_DISABLE_ALL_DRIVERS
- return DRV_IsRunning("SHT3X") || DRV_IsRunning("CHT8305");
+ return DRV_IsRunning("SHT3X") || DRV_IsRunning("CHT8305") || DRV_IsRunning("SGP");
#else
return false;
#endif
diff --git a/src/driver/drv_sgp.c b/src/driver/drv_sgp.c
new file mode 100644
index 000000000..d34d279ec
--- /dev/null
+++ b/src/driver/drv_sgp.c
@@ -0,0 +1,268 @@
+#include "../new_common.h"
+#include "../new_pins.h"
+#include "../new_cfg.h"
+// Commands register, execution API and cmd tokenizer
+#include "../cmnds/cmd_public.h"
+#include "../mqtt/new_mqtt.h"
+#include "../logging/logging.h"
+#include "drv_local.h"
+#include "drv_uart.h"
+#include "../httpserver/new_http.h"
+#include "../hal/hal_pins.h"
+
+#include "drv_sgp.h"
+
+
+#define SGP_I2C_ADDRESS (0x58 << 1)
+
+static byte channel_co2 = 0, channel_tvoc = 0, g_sgpcycle = 1, g_sgpcycleref = 10, g_sgpstate = 0;
+static float g_co2 = 0.0, g_tvoc = 0.0;
+static softI2C_t g_sgpI2C;
+
+
+void SGP_Readmeasure() {
+#if WINDOWS
+ // TODO: values for simulator so I can test SGP
+ // on my Windows machine
+ g_co2 = 120;
+ g_tvoc = 130;
+#else
+ uint8_t buff[6];
+ unsigned int th, tl, hh, hl;
+
+ // launch measurement on sensor.
+ Soft_I2C_Start(&g_sgpI2C, SGP_I2C_ADDRESS);
+ Soft_I2C_WriteByte(&g_sgpI2C, 0x20);
+ Soft_I2C_WriteByte(&g_sgpI2C, 0x08);
+ Soft_I2C_Stop(&g_sgpI2C);
+
+ rtos_delay_milliseconds(12);
+
+ Soft_I2C_Start(&g_sgpI2C, SGP_I2C_ADDRESS | 1);
+ Soft_I2C_ReadBytes(&g_sgpI2C, buff, 6);
+ Soft_I2C_Stop(&g_sgpI2C);
+
+ th = buff[0];
+ tl = buff[1];
+ hh = buff[3];
+ hl = buff[4];
+
+ addLogAdv(LOG_DEBUG, LOG_FEATURE_SENSOR, "SGP_Measure: Bits %02X %02X %02X %02X", buff[0], buff[1], buff[3], buff[4]);
+
+ g_co2 = ((th * 256 + tl));
+ g_tvoc = ((hh * 256 + hl));
+#endif
+
+ channel_co2 = g_cfg.pins.channels[g_sgpI2C.pin_data];
+ channel_tvoc = g_cfg.pins.channels2[g_sgpI2C.pin_data];
+ if (g_co2 == 400.00 && g_tvoc == 0.00)
+ {
+ addLogAdv(LOG_INFO, LOG_FEATURE_SENSOR, "SGP_Measure: Baseline init in progress");
+ g_sgpstate = 0;
+ }
+ else {
+ g_sgpstate = 1;
+ CHANNEL_Set(channel_co2, (int)(g_co2), 0);
+ CHANNEL_Set(channel_tvoc, (int)(g_tvoc), 0);
+ }
+ addLogAdv(LOG_INFO, LOG_FEATURE_SENSOR, "SGP_Measure: CO2 :%.1f ppm tvoc:%.0f ppb", g_co2, g_tvoc);
+}
+
+// StopDriver SGP
+void SGP_StopDriver() {
+ addLogAdv(LOG_INFO, LOG_FEATURE_SENSOR, "SGP : Stopping Driver and reset sensor");
+}
+
+
+void SGP_GetBaseline()
+{
+ uint32_t baseline;
+ uint8_t buff[6];
+ // launch measurement on sensor.
+ Soft_I2C_Start(&g_sgpI2C, SGP_I2C_ADDRESS);
+ Soft_I2C_WriteByte(&g_sgpI2C, 0x20);
+ Soft_I2C_WriteByte(&g_sgpI2C, 0x15);
+ Soft_I2C_Stop(&g_sgpI2C);
+
+ rtos_delay_milliseconds(10);
+
+ Soft_I2C_Start(&g_sgpI2C, SGP_I2C_ADDRESS | 1);
+ Soft_I2C_ReadBytes(&g_sgpI2C, buff, 6);
+ Soft_I2C_Stop(&g_sgpI2C);
+
+ addLogAdv(LOG_INFO, LOG_FEATURE_SENSOR, "SGP : baseline : %02X %02X %02X %02X", buff[0], buff[1], buff[3], buff[4]);
+}
+commandResult_t SGP_GetBaselinecmd(const void* context, const char* cmd, const char* args, int cmdFlags)
+{
+ SGP_GetBaseline();
+ return CMD_RES_OK;
+}
+
+void SGP_GetVersion()
+{
+ uint32_t baseline;
+ uint8_t buff[3];
+ uint16_t feature_set_version;
+ uint8_t product_type;
+
+ // launch measurement on sensor.
+ Soft_I2C_Start(&g_sgpI2C, SGP_I2C_ADDRESS);
+ Soft_I2C_WriteByte(&g_sgpI2C, 0x20);
+ Soft_I2C_WriteByte(&g_sgpI2C, 0x2f);
+ Soft_I2C_Stop(&g_sgpI2C);
+
+ rtos_delay_milliseconds(10);
+
+ Soft_I2C_Start(&g_sgpI2C, SGP_I2C_ADDRESS | 1);
+ Soft_I2C_ReadBytes(&g_sgpI2C, buff, 3);
+ Soft_I2C_Stop(&g_sgpI2C);
+ feature_set_version = ((buff[1] * 256) + buff[0]);
+ product_type = (uint8_t)((feature_set_version & 0xF000) >> 12);
+ feature_set_version = feature_set_version & 0x00FF;
+
+ addLogAdv(LOG_INFO, LOG_FEATURE_SENSOR, "SGP : Version : %i %i ", feature_set_version, product_type);
+}
+commandResult_t SGP_GetVersioncmd(const void* context, const char* cmd, const char* args, int cmdFlags)
+{
+ SGP_GetVersion();
+ return CMD_RES_OK;
+}
+
+void SGP_SoftReset()
+{
+ Soft_I2C_Start(&g_sgpI2C, SGP_I2C_ADDRESS);
+ Soft_I2C_WriteByte(&g_sgpI2C, 0x00); //Clear status
+ Soft_I2C_WriteByte(&g_sgpI2C, 0x06); //clear status
+ Soft_I2C_Stop(&g_sgpI2C);
+ addLogAdv(LOG_INFO, LOG_FEATURE_SENSOR, "SGP : SOFT RESET");
+}
+commandResult_t SGP_SoftResetcmd(const void* context, const char* cmd, const char* args, int cmdFlags)
+{
+ SGP_SoftReset();
+ return CMD_RES_OK;
+}
+
+void SGP_INIT_BASELINE()
+{
+ Soft_I2C_Start(&g_sgpI2C, SGP_I2C_ADDRESS);
+ Soft_I2C_WriteByte(&g_sgpI2C, 0x20);
+ Soft_I2C_WriteByte(&g_sgpI2C, 0x03);
+ Soft_I2C_Stop(&g_sgpI2C);
+ addLogAdv(LOG_INFO, LOG_FEATURE_SENSOR, "SGP : Launch INIT Baseline");
+}
+
+
+// Read Baseline
+static void SGP_Read_IAQ(float* co2, float* tvoc)
+{
+}
+
+static uint8_t SGP_CalcCrc(uint8_t* data)
+{
+ uint8_t bit; // bit mask
+ uint8_t crc = 0xFF; // calculated checksum
+
+ // calculates 8-Bit checksum with given polynomial
+ crc ^= (data[0]);
+ for (bit = 8; bit > 0; --bit)
+ {
+ if ((crc & 0x80))
+ {
+ crc = (crc << 1) ^ 0x131;
+ }
+ else
+ {
+ crc = (crc << 1);
+ }
+ }
+
+ crc ^= (data[1]);
+ for (bit = 8; bit > 0; --bit)
+ {
+ if ((crc & 0x80))
+ {
+ crc = (crc << 1) ^ 0x131;
+ }
+ else
+ {
+ crc = (crc << 1);
+ }
+ }
+
+ return crc;
+}
+commandResult_t SGP_cycle(const void* context, const char* cmd, const char* args, int cmdFlags) {
+
+ Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND);
+ if (Tokenizer_GetArgsCount() < 1) {
+ ADDLOG_INFO(LOG_FEATURE_CMD, "SHT Cycle : Need integer args for seconds cycle");
+ return CMD_RES_NOT_ENOUGH_ARGUMENTS;
+ }
+ g_sgpcycleref = Tokenizer_GetArgFloat(0);
+
+ ADDLOG_INFO(LOG_FEATURE_CMD, "SGP Cycle : Measurement will run every %i seconds", g_sgpcycleref);
+
+ return CMD_RES_OK;
+}
+// startDriver SGP
+void SGP_Init() {
+
+
+ g_sgpI2C.pin_clk = 9;
+ g_sgpI2C.pin_data = 14;
+
+ g_sgpI2C.pin_clk = PIN_FindPinIndexForRole(IOR_SGP_CLK, g_sgpI2C.pin_clk);
+ g_sgpI2C.pin_data = PIN_FindPinIndexForRole(IOR_SGP_DAT, g_sgpI2C.pin_data);
+
+ Soft_I2C_PreInit(&g_sgpI2C);
+
+ //init the baseline
+ SGP_INIT_BASELINE();
+
+ rtos_delay_milliseconds(10);
+
+ //cmddetail:{"name":"SGP_cycle","args":"[int]",
+ //cmddetail:"descr":"change cycle of measurement by default every 10 seconds 0 to deactivate",
+ //cmddetail:"fn":"SGP_cycle","file":"drv/drv_sgp.c","requires":"",
+ //cmddetail:"examples":"SGP_Cycle 60"}
+ CMD_RegisterCommand("SGP_cycle", SGP_cycle, NULL);
+ //cmddetail:{"name":"SGP_GetVersion","args":"",
+ //cmddetail:"descr":"SGP : get version",
+ //cmddetail:"fn":"SGP_GetVersion","file":"drv/drv_sgp.c","requires":"",
+ //cmddetail:"examples":"SGP_GetVersion"}
+ CMD_RegisterCommand("SGP_GetVersion", SGP_GetVersioncmd, NULL);
+ //cmddetail:{"name":"SGP_GetBaseline","args":"",
+ //cmddetail:"descr":"SGP Get baseline",
+ //cmddetail:"fn":"SGP_GetBaseline","file":"drv/drv_sgp.c","requires":"",
+ //cmddetail:"examples":"SGP_GetBaseline"}
+ CMD_RegisterCommand("SGP_GetBaseline", SGP_GetBaselinecmd, NULL);
+ //cmddetail:{"name":"SGP_SoftReset","args":"",
+ //cmddetail:"descr":"SGP i2C soft reset",
+ //cmddetail:"fn":"SGP_SoftReset","file":"drv/drv_sgp.c","requires":"",
+ //cmddetail:"examples":"SGP_SoftReset"}
+ CMD_RegisterCommand("SGP_SoftReset", SGP_SoftResetcmd, NULL);
+}
+void SGP_OnEverySecond()
+{
+
+ if (g_sgpcycle == 1 || g_sgpstate == 0) {
+ SGP_Readmeasure();
+ g_sgpcycle = g_sgpcycleref;
+ }
+ if (g_sgpcycle > 0) {
+ --g_sgpcycle;
+ }
+ ADDLOG_DEBUG(LOG_FEATURE_DRV, "DRV_SGP : Measurement will run in %i cycle", g_sgpcycle);
+}
+
+void SGP_AppendInformationToHTTPIndexPage(http_request_t* request)
+{
+
+ hprintf255(request, "
SGP CO2=%.1f ppm, TVoc=%.0f ppb
", g_co2, g_tvoc);
+ if (channel_co2 == channel_tvoc) {
+ hprintf255(request, "WARNING: You don't have configured target channels for co2 and tvoc results, set the first and second channel index in Pins!");
+ }
+ if (g_sgpstate == 0) {
+ hprintf255(request, "WARNING: Baseline calculation in progress");
+ }
+}
diff --git a/src/driver/drv_sgp.h b/src/driver/drv_sgp.h
new file mode 100644
index 000000000..c94d2d428
--- /dev/null
+++ b/src/driver/drv_sgp.h
@@ -0,0 +1,56 @@
+#define SGT_DELAY 4
+#define SGT_INIT_DELAY 30
+
+#define SGP30_PRODUCT_TYPE 0
+
+/* command and constants for reading the serial ID */
+#define SGP30_CMD_GET_SERIAL_ID 0x3682
+#define SGP30_CMD_GET_SERIAL_ID_DURATION_US 500
+#define SGP30_CMD_GET_SERIAL_ID_WORDS 3
+
+/* command and constants for reading the featureset version */
+#define SGP30_CMD_GET_FEATURESET 0x202f
+#define SGP30_CMD_GET_FEATURESET_DURATION_US 10000
+#define SGP30_CMD_GET_FEATURESET_WORDS 1
+
+/* command and constants for on-chip self-test */
+#define SGP30_CMD_MEASURE_TEST 0x2032
+#define SGP30_CMD_MEASURE_TEST_DURATION_US 220000
+#define SGP30_CMD_MEASURE_TEST_WORDS 1
+#define SGP30_CMD_MEASURE_TEST_OK 0xd400
+
+/* command and constants for IAQ init */
+#define SGP30_CMD_IAQ_INIT 0x2003
+#define SGP30_CMD_IAQ_INIT_DURATION_US 10000
+
+/* command and constants for IAQ measure */
+#define SGP30_CMD_IAQ_MEASURE 0x2008
+#define SGP30_CMD_IAQ_MEASURE_DURATION_US 12000
+#define SGP30_CMD_IAQ_MEASURE_WORDS 2
+
+/* command and constants for getting IAQ baseline */
+#define SGP30_CMD_GET_IAQ_BASELINE 0x2015
+#define SGP30_CMD_GET_IAQ_BASELINE_DURATION_US 10000
+#define SGP30_CMD_GET_IAQ_BASELINE_WORDS 2
+
+/* command and constants for setting IAQ baseline */
+#define SGP30_CMD_SET_IAQ_BASELINE 0x201e
+#define SGP30_CMD_SET_IAQ_BASELINE_DURATION_US 10000
+
+/* command and constants for raw measure */
+#define SGP30_CMD_RAW_MEASURE 0x2050
+#define SGP30_CMD_RAW_MEASURE_DURATION_US 25000
+#define SGP30_CMD_RAW_MEASURE_WORDS 2
+
+/* command and constants for setting absolute humidity */
+#define SGP30_CMD_SET_ABSOLUTE_HUMIDITY 0x2061
+#define SGP30_CMD_SET_ABSOLUTE_HUMIDITY_DURATION_US 10000
+
+/* command and constants for getting TVOC inceptive baseline */
+#define SGP30_CMD_GET_TVOC_INCEPTIVE_BASELINE 0x20b3
+#define SGP30_CMD_GET_TVOC_INCEPTIVE_BASELINE_DURATION_US 10000
+#define SGP30_CMD_GET_TVOC_INCEPTIVE_BASELINE_WORDS 1
+
+/* command and constants for setting TVOC baseline */
+#define SGP30_CMD_SET_TVOC_BASELINE 0x2077
+#define SGP30_CMD_SET_TVOC_BASELINE_DURATION_US 10000
diff --git a/src/driver/drv_tuyaMCU.c b/src/driver/drv_tuyaMCU.c
index aefc56f62..d42c626a8 100644
--- a/src/driver/drv_tuyaMCU.c
+++ b/src/driver/drv_tuyaMCU.c
@@ -19,6 +19,7 @@ https://developer.tuya.com/en/docs/iot/tuyacloudlowpoweruniversalserialaccesspro
#include "../logging/logging.h"
#include "../hal/hal_wifi.h"
#include "../mqtt/new_mqtt.h"
+#include "drv_public.h"
#include "drv_tuyaMCU.h"
#include "drv_uart.h"
#include "drv_public.h"
@@ -68,84 +69,84 @@ void TuyaMCU_RunFrame();
#define DP_TYPE_RAW_TAC2121C_YESTERDAY 202
#define DP_TYPE_RAW_TAC2121C_LASTMONTH 203
-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";
+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";
}
-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";
+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";
if (t == TUYA_CMD_WEATHERDATA)
return "WeatherData";
- if (t == TUYA_CMD_NETWORK_STATUS)
- return "NetworkStatus";
- if (t == TUYA_CMD_SET_RSSI)
- return "SetRSSI";
- return "Unknown";
+ if (t == TUYA_CMD_NETWORK_STATUS)
+ return "NetworkStatus";
+ if (t == TUYA_CMD_SET_RSSI)
+ return "SetRSSI";
+ 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;
+tuyaMCUMapping_t* g_tuyaMappings = 0;
/**
* Dimmer range
@@ -153,7 +154,7 @@ tuyaMCUMapping_t *g_tuyaMappings = 0;
* 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
+ // minimum dimmer value as reported by TuyaMCU dimmer
int g_dimmerRangeMin = 0;
// maximum dimmer value as reported by TuyaMCU dimmer
int g_dimmerRangeMax = 100;
@@ -181,45 +182,45 @@ static int g_sendQueryStatePackets = 0;
// See: https://imgur.com/a/mEfhfiA
static byte g_defaultTuyaMCUWiFiState = 0x00;
-tuyaMCUMapping_t *TuyaMCU_FindDefForID(int fnId) {
- tuyaMCUMapping_t *cur;
+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;
+ 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* TuyaMCU_FindDefForChannel(int channel) {
+ 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;
}
@@ -227,159 +228,161 @@ void TuyaMCU_MapIDToChannel(int fnId, int dpType, int channel) {
// 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 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];
- 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)) {
- snprintf(buffer2, sizeof(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)) {
+ snprintf(buffer2, sizeof(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;
}
// append header, len, everything, checksum
-void TuyaMCU_SendCommandWithData(byte cmdType, byte *data, int payload_len) {
- int i;
+void TuyaMCU_SendCommandWithData(byte cmdType, byte* data, int payload_len) {
+ 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)
{
- 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;
+ 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);
+ 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);
+ 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));
+ 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));
+ TuyaMCU_SendState(id, DP_TYPE_ENUM, (uint8_t*)(&value));
}
-static uint16_t convertHexStringtoBytes (uint8_t * dest, char src[], uint16_t src_len){
- char hexbyte[3];
- uint16_t i;
+static uint16_t convertHexStringtoBytes(uint8_t* dest, char src[], uint16_t src_len) {
+ char hexbyte[3];
+ uint16_t i;
- if (NULL == dest || NULL == src || 0 == src_len){
- return 0;
- }
+ if (NULL == dest || NULL == src || 0 == src_len) {
+ return 0;
+ }
- hexbyte[2] = 0;
+ hexbyte[2] = 0;
- for (i = 0; i < src_len; i++) {
- hexbyte[0] = src[2*i];
- hexbyte[1] = src[2*i+1];
- dest[i] = strtol(hexbyte, NULL, 16);
- }
+ 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;
+ return i;
}
void TuyaMCU_SendHexString(uint8_t id, char data[]) {
@@ -387,17 +390,17 @@ void TuyaMCU_SendHexString(uint8_t id, char data[]) {
#else
- 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;
+ 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;
- convertHexStringtoBytes(&payload_buffer[4], data, len);
+ convertHexStringtoBytes(&payload_buffer[4], data, len);
- TuyaMCU_SendCommandWithData(TUYA_CMD_SET_DP, payload_buffer, payload_len);
+ TuyaMCU_SendCommandWithData(TUYA_CMD_SET_DP, payload_buffer, payload_len);
#endif
}
@@ -405,19 +408,19 @@ void TuyaMCU_SendString(uint8_t id, char data[]) {
#ifdef WIN32
#else
- 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;
+ 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];
- }
+ for (uint16_t i = 0; i < len; i++) {
+ payload_buffer[4 + i] = data[i];
+ }
- TuyaMCU_SendCommandWithData(TUYA_CMD_SET_DP, payload_buffer, payload_len);
+ TuyaMCU_SendCommandWithData(TUYA_CMD_SET_DP, payload_buffer, payload_len);
#endif
}
@@ -425,33 +428,34 @@ void TuyaMCU_SendRaw(uint8_t id, char data[]) {
#ifdef WIN32
#else
- 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;
+ 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;
- convertHexStringtoBytes(&payload_buffer[4], beginPos, len);
+ convertHexStringtoBytes(&payload_buffer[4], beginPos, len);
- TuyaMCU_SendCommandWithData(TUYA_CMD_SET_DP, payload_buffer, payload_len);
+ TuyaMCU_SendCommandWithData(TUYA_CMD_SET_DP, payload_buffer, payload_len);
#endif
}
/*
For setting the Wifi Signal Strength. I tested by using the following.
-Take the RSSI for the front web interface (eg -54), calculate the 2's complement (0xCA),
+Take the RSSI for the front web interface (eg -54), calculate the 2's complement (0xCA),
and manually calculate the checksum and it works.
"uartSendHex 55AA 00 24 0001 CA EE"
*/
@@ -464,13 +468,13 @@ void TuyaMCU_Send_RSSI(int rssi) {
}
// See this post to find about about arguments of WiFi state
// https://www.elektroda.com/rtvforum/viewtopic.php?p=20483899#20483899
-commandResult_t Cmd_TuyaMCU_Set_DefaultWiFiState(const void *context, const char *cmd, const char *args, int cmdFlags) {
-
+commandResult_t Cmd_TuyaMCU_Set_DefaultWiFiState(const void* context, const char* cmd, const char* args, int cmdFlags) {
+
g_defaultTuyaMCUWiFiState = atoi(args);
-
+
return CMD_RES_OK;
}
-commandResult_t Cmd_TuyaMCU_Send_RSSI(const void *context, const char *cmd, const char *args, int cmdFlags) {
+commandResult_t Cmd_TuyaMCU_Send_RSSI(const void* context, const char* cmd, const char* args, int cmdFlags) {
int toSend;
Tokenizer_TokenizeString(args, 0);
@@ -484,8 +488,8 @@ commandResult_t Cmd_TuyaMCU_Send_RSSI(const void *context, const char *cmd, cons
TuyaMCU_Send_RSSI(toSend);
return CMD_RES_OK;
}
-void TuyaMCU_Send_SetTime(struct tm *pTime) {
- byte payload_buffer[8];
+void TuyaMCU_Send_SetTime(struct tm* pTime) {
+ byte payload_buffer[8];
if (pTime == 0) {
memset(payload_buffer, 0, sizeof(payload_buffer));
@@ -515,25 +519,25 @@ void TuyaMCU_Send_SetTime(struct tm *pTime) {
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() {
- struct tm * ptm;
+struct tm* TuyaMCU_Get_NTP_Time() {
+ struct tm* ptm;
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"MCU time to set: %i\n", g_ntpTime);
- ptm = gmtime((time_t*)&g_ntpTime);
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "MCU time to set: %i\n", g_ntpTime);
+ ptm = gmtime((time_t*)&g_ntpTime);
if (ptm != 0) {
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;
}
-void TuyaMCU_Send_RawBuffer(byte *data, int len) {
- int i;
+void TuyaMCU_Send_RawBuffer(byte* data, int len) {
+ 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:
@@ -543,27 +547,27 @@ void TuyaMCU_Send_RawBuffer(byte *data, int len) {
// uartSendHex 55AA000200010406
/*Info:MAIN:Time 143, free 88864, MQTT 1, bWifi 1, secondsWithNoPing -1, socks 2/38
-Info:TuyaMCU:TUYAMCU received: 55 AA 00 08 00 0C 00 02 02 02 02 02 02 01 04 00 01 00 25
+Info:TuyaMCU:TUYAMCU received: 55 AA 00 08 00 0C 00 02 02 02 02 02 02 01 04 00 01 00 25
Info:TuyaMCU:TuyaMCU_ProcessIncoming: processing V0 command 8 with 19 bytes
Info:TuyaMCU:TuyaMCU_V0_ParseRealTimeWithRecordStorage: processing dpId 1, dataType 4-DP_TYPE_ENUM and 1 data bytes
-Info:TuyaMCU:TuyaMCU_V0_ParseRealTimeWithRecordStorage: raw data 1 byte:
+Info:TuyaMCU:TuyaMCU_V0_ParseRealTimeWithRecordStorage: raw data 1 byte:
Info:GEN:No change in channel 1 (still set to 0) - ignoring
*/
-commandResult_t TuyaMCU_LinkTuyaMCUOutputToChannel(const void *context, const char *cmd, const char *args, int cmdFlags) {
- int dpId;
- const char *dpTypeString;
- int dpType;
- int channelID;
+commandResult_t TuyaMCU_LinkTuyaMCUOutputToChannel(const void* context, const char* cmd, const char* args, int cmdFlags) {
+ int dpId;
+ const char* dpTypeString;
+ int dpType;
+ int channelID;
int argsCount;
- // linkTuyaMCUOutputToChannel dpId varType channelID
- // linkTuyaMCUOutputToChannel 1 val 1
- Tokenizer_TokenizeString(args,0);
+ // linkTuyaMCUOutputToChannel dpId varType channelID
+ // linkTuyaMCUOutputToChannel 1 val 1
+ Tokenizer_TokenizeString(args, 0);
argsCount = Tokenizer_GetArgsCount();
// following check must be done after 'Tokenizer_TokenizeString',
@@ -572,19 +576,24 @@ commandResult_t TuyaMCU_LinkTuyaMCUOutputToChannel(const void *context, const ch
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 2)) {
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
}
- 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 (!stricmp(dpTypeString, "RAW_DDS238")) {
+ 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 (!stricmp(dpTypeString, "RAW_DDS238")) {
// linkTuyaMCUOutputToChannel 6 RAW_DDS238
dpType = DP_TYPE_RAW_DDS238Packet;
}
@@ -597,64 +606,66 @@ commandResult_t TuyaMCU_LinkTuyaMCUOutputToChannel(const void *context, const ch
}
else if (!stricmp(dpTypeString, "RAW_TAC2121C_LastMonth")) {
dpType = DP_TYPE_RAW_TAC2121C_LASTMONTH;
- } 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 CMD_RES_BAD_ARGUMENT;
- }
- }
+ }
+ 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 CMD_RES_BAD_ARGUMENT;
+ }
+ }
if (argsCount < 2) {
channelID = -999;
}
else {
channelID = Tokenizer_GetArgInteger(2);
}
-
- TuyaMCU_MapIDToChannel(dpId, dpType, channelID);
- return CMD_RES_OK;
+ TuyaMCU_MapIDToChannel(dpId, dpType, channelID);
+
+ return CMD_RES_OK;
}
-commandResult_t TuyaMCU_Send_SetTime_Current(const void *context, const char *cmd, const char *args, int cmdFlags) {
+commandResult_t 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 CMD_RES_OK;
+ return CMD_RES_OK;
}
-commandResult_t TuyaMCU_Send_SetTime_Example(const void *context, const char *cmd, const char *args, int cmdFlags) {
- struct tm testTime;
+commandResult_t TuyaMCU_Send_SetTime_Example(const void* context, const char* cmd, const char* args, int cmdFlags) {
+ 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 CMD_RES_OK;
+ TuyaMCU_Send_SetTime(&testTime);
+ return CMD_RES_OK;
}
-void TuyaMCU_Send(byte *data, int size) {
- int i;
- unsigned char check_sum;
+void TuyaMCU_Send(byte* data, int size) {
+ 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);
}
-commandResult_t TuyaMCU_SetDimmerRange(const void *context, const char *cmd, const char *args, int cmdFlags) {
- Tokenizer_TokenizeString(args,0);
+commandResult_t TuyaMCU_SetDimmerRange(const void* context, const char* cmd, const char* args, int cmdFlags) {
+ Tokenizer_TokenizeString(args, 0);
// following check must be done after 'Tokenizer_TokenizeString',
// so we know arguments count in Tokenizer. 'cmd' argument is
// only for warning display
@@ -662,36 +673,36 @@ commandResult_t TuyaMCU_SetDimmerRange(const void *context, const char *cmd, con
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
}
- g_dimmerRangeMin = Tokenizer_GetArgInteger(0);
- g_dimmerRangeMax = Tokenizer_GetArgInteger(1);
+ g_dimmerRangeMin = Tokenizer_GetArgInteger(0);
+ g_dimmerRangeMax = Tokenizer_GetArgInteger(1);
- return CMD_RES_OK;
+ return CMD_RES_OK;
}
-commandResult_t TuyaMCU_SendHeartbeat(const void *context, const char *cmd, const char *args, int cmdFlags) {
- TuyaMCU_SendCommandWithData(TUYA_CMD_HEARTBEAT, NULL, 0);
+commandResult_t TuyaMCU_SendHeartbeat(const void* context, const char* cmd, const char* args, int cmdFlags) {
+ TuyaMCU_SendCommandWithData(TUYA_CMD_HEARTBEAT, NULL, 0);
- return CMD_RES_OK;
+ return CMD_RES_OK;
}
-commandResult_t TuyaMCU_SendQueryProductInformation(const void *context, const char *cmd, const char *args, int cmdFlags) {
- TuyaMCU_SendCommandWithData(TUYA_CMD_QUERY_PRODUCT, NULL, 0);
+commandResult_t TuyaMCU_SendQueryProductInformation(const void* context, const char* cmd, const char* args, int cmdFlags) {
+ TuyaMCU_SendCommandWithData(TUYA_CMD_QUERY_PRODUCT, NULL, 0);
- return CMD_RES_OK;
+ return CMD_RES_OK;
}
-commandResult_t TuyaMCU_SendQueryState(const void *context, const char *cmd, const char *args, int cmdFlags) {
- TuyaMCU_SendCommandWithData(TUYA_CMD_QUERY_STATE, NULL, 0);
+commandResult_t TuyaMCU_SendQueryState(const void* context, const char* cmd, const char* args, int cmdFlags) {
+ TuyaMCU_SendCommandWithData(TUYA_CMD_QUERY_STATE, NULL, 0);
- return CMD_RES_OK;
+ return CMD_RES_OK;
}
-commandResult_t TuyaMCU_SendStateCmd(const void *context, const char *cmd, const char *args, int cmdFlags) {
- int dpId;
- int dpType;
- int value;
+commandResult_t TuyaMCU_SendStateCmd(const void* context, const char* cmd, const char* args, int cmdFlags) {
+ int dpId;
+ int dpType;
+ int value;
- Tokenizer_TokenizeString(args,0);
+ Tokenizer_TokenizeString(args, 0);
// following check must be done after 'Tokenizer_TokenizeString',
// so we know arguments count in Tokenizer. 'cmd' argument is
// only for warning display
@@ -699,43 +710,44 @@ commandResult_t TuyaMCU_SendStateCmd(const void *context, const char *cmd, const
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
}
- 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 CMD_RES_OK;
+ return CMD_RES_OK;
}
-commandResult_t TuyaMCU_SendMCUConf(const void *context, const char *cmd, const char *args, int cmdFlags) {
- TuyaMCU_SendCommandWithData(TUYA_CMD_MCU_CONF, NULL, 0);
+commandResult_t TuyaMCU_SendMCUConf(const void* context, const char* cmd, const char* args, int cmdFlags) {
+ TuyaMCU_SendCommandWithData(TUYA_CMD_MCU_CONF, NULL, 0);
- return CMD_RES_OK;
+ return CMD_RES_OK;
}
void Tuya_SetWifiState(uint8_t state)
{
- TuyaMCU_SendCommandWithData(TUYA_CMD_WIFI_STATE, &state, 1);
+ TuyaMCU_SendCommandWithData(TUYA_CMD_WIFI_STATE, &state, 1);
}
void TuyaMCU_SendNetworkStatus()
{
- uint8_t state = TUYA_NETWORK_STATUS_NOT_CONNECTED;
- if (Main_IsOpenAccessPointMode() != 0 ) {
- state = TUYA_NETWORK_STATUS_AP_MODE;
- } else if (Main_HasWiFiConnected() != 0 ){
- state = Main_HasMQTTConnected() != 0? TUYA_NETWORK_STATUS_CONNECTED_TO_CLOUD : TUYA_NETWORK_STATUS_CONNECTED_TO_ROUTER;
- }
- addLogAdv(LOG_DEBUG, LOG_FEATURE_TUYAMCU,"TuyaMCU_SendNetworkStatus: sending status 0x%X to MCU \n", state);
- TuyaMCU_SendCommandWithData(0x2B, &state, 1);
+ uint8_t state = TUYA_NETWORK_STATUS_NOT_CONNECTED;
+ if (Main_IsOpenAccessPointMode() != 0) {
+ state = TUYA_NETWORK_STATUS_AP_MODE;
+ }
+ else if (Main_HasWiFiConnected() != 0) {
+ state = Main_HasMQTTConnected() != 0 ? TUYA_NETWORK_STATUS_CONNECTED_TO_CLOUD : TUYA_NETWORK_STATUS_CONNECTED_TO_ROUTER;
+ }
+ addLogAdv(LOG_DEBUG, LOG_FEATURE_TUYAMCU, "TuyaMCU_SendNetworkStatus: sending status 0x%X to MCU \n", state);
+ TuyaMCU_SendCommandWithData(0x2B, &state, 1);
}
void TuyaMCU_ForcePublishChannelValues() {
- tuyaMCUMapping_t *cur;
+ tuyaMCUMapping_t* cur;
cur = g_tuyaMappings;
while (cur) {
- MQTT_ChannelPublish(cur->channel,0);
+ MQTT_ChannelPublish(cur->channel, 0);
cur = cur->next;
}
return 0;
@@ -752,47 +764,47 @@ void TuyaMCU_ForcePublishChannelValues() {
// 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;
- case ChType_Dimmer1000:
- // map TuyaMCU's dimmer range to OpenBK7231T_App's dimmer range 0..1000
- mappedValue = ((value - g_dimmerRangeMin) * 1000) / (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;
+ case ChType_Dimmer1000:
+ // map TuyaMCU's dimmer range to OpenBK7231T_App's dimmer range 0..1000
+ mappedValue = ((value - g_dimmerRangeMin) * 1000) / (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);
}
bool TuyaMCU_IsChannelUsedByTuyaMCU(int channel) {
- tuyaMCUMapping_t *mapping;
+ tuyaMCUMapping_t* mapping;
// find mapping
mapping = TuyaMCU_FindDefForChannel(channel);
@@ -803,80 +815,80 @@ bool TuyaMCU_IsChannelUsedByTuyaMCU(int channel) {
return true;
}
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;
- case ChType_Dimmer1000:
- // map OpenBK7231T_App's dimmer range 0..256 to TuyaMCU's dimmer range
- mappediVal = (((g_dimmerRangeMax - g_dimmerRangeMin) * iVal) / 1000) + 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;
+ case ChType_Dimmer1000:
+ // map OpenBK7231T_App's dimmer range 0..256 to TuyaMCU's dimmer range
+ mappediVal = (((g_dimmerRangeMax - g_dimmerRangeMin) * iVal) / 1000) + 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;
+void TuyaMCU_ParseQueryProductInformation(const byte* data, int len) {
+ 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);
}
// See: https://www.elektroda.com/rtvforum/viewtopic.php?p=20345606#20345606
-void TuyaMCU_ParseWeatherData(const byte *data, int len) {
+void TuyaMCU_ParseWeatherData(const byte* data, int len) {
int ofs;
byte bValid;
//int checkLen;
@@ -884,7 +896,7 @@ void TuyaMCU_ParseWeatherData(const byte *data, int len) {
byte stringLen;
byte varType;
char buffer[64];
- const char *stringData;
+ const char* stringData;
//const char *stringDataValue;
ofs = 0;
@@ -916,7 +928,7 @@ void TuyaMCU_ParseWeatherData(const byte *data, int len) {
else {
iValue = 0;
}
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "TuyaMCU_ParseWeatherData: key %s, val integer %i\n",buffer, iValue);
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "TuyaMCU_ParseWeatherData: key %s, val integer %i\n", buffer, iValue);
}
else {
// string
@@ -941,11 +953,11 @@ void TuyaMCU_ParseWeatherData(const byte *data, int len) {
// 55AA 00 06 0005 10 0100 01 00 1C
// Head v0 ID lengh fnId leen tp vl CHKSUM
-void TuyaMCU_V0_ParseRealTimeWithRecordStorage(const byte *data, int len, bool bIncludesDate) {
- int ofs;
- int sectorLen;
- int fnId;
- int dataType;
+void TuyaMCU_V0_ParseRealTimeWithRecordStorage(const byte* data, int len, bool bIncludesDate) {
+ int ofs;
+ int sectorLen;
+ int fnId;
+ int dataType;
if (bIncludesDate) {
//data[0]; // bDateValid
@@ -962,143 +974,144 @@ void TuyaMCU_V0_ParseRealTimeWithRecordStorage(const byte *data, int len, bool b
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_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;
+void TuyaMCU_ParseStateMessage(const byte* data, int len) {
+ int ofs;
+ int sectorLen;
+ int fnId;
+ int dataType;
int day, month, year;
//int channelType;
int iVal;
- 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) {
- 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);
- }
- else if(sectorLen == 4) {
- 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) {
+ 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);
+ }
+ else if (sectorLen == 4) {
+ 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);
+ }
else {
- tuyaMCUMapping_t *mapping;
+ tuyaMCUMapping_t* mapping;
mapping = TuyaMCU_FindDefForID(fnId);
if (mapping != 0) {
switch (mapping->dpType) {
- case DP_TYPE_RAW_TAC2121C_YESTERDAY:
- {
- if (sectorLen != 8) {
+ case DP_TYPE_RAW_TAC2121C_YESTERDAY:
+ {
+ if (sectorLen != 8) {
- }
- else {
- month = data[ofs + 4];
- day = data[ofs + 4 + 1];
- // consumption
- iVal = data[ofs + 6 + 4] << 8 | data[ofs + 7 + 4];
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "TAC2121C_YESTERDAY: day %i, month %i, val %i\n",
- day, month, iVal);
-
- }
}
- break;
- case DP_TYPE_RAW_TAC2121C_LASTMONTH:
- {
- if (sectorLen != 8) {
+ else {
+ month = data[ofs + 4];
+ day = data[ofs + 4 + 1];
+ // consumption
+ iVal = data[ofs + 6 + 4] << 8 | data[ofs + 7 + 4];
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "TAC2121C_YESTERDAY: day %i, month %i, val %i\n",
+ day, month, iVal);
- }
- else {
- year = data[ofs + 4];
- month = data[ofs + 4 + 1];
- // consumption
- iVal = data[ofs + 6 + 4] << 8 | data[ofs + 7 + 4];
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "DP_TYPE_RAW_TAC2121C_LASTMONTH: month %i, year %i, val %i\n",
- month, year, iVal);
-
- }
}
- break;
- case DP_TYPE_RAW_TAC2121C_VCP:
- {
- if (sectorLen == 8 || sectorLen == 10) {
- // voltage
- iVal = data[ofs + 0 + 4] << 8 | data[ofs + 1 + 4];
- CHANNEL_SetAllChannelsByType(ChType_Voltage_div10, iVal);
- // current
- iVal = data[ofs + 3 + 4] << 8 | data[ofs + 4 + 4];
- CHANNEL_SetAllChannelsByType(ChType_Current_div1000, iVal);
- // power
- iVal = data[ofs + 6 + 4] << 8 | data[ofs + 7 + 4];
- CHANNEL_SetAllChannelsByType(ChType_Power, iVal);
- }
- else {
+ }
+ break;
+ case DP_TYPE_RAW_TAC2121C_LASTMONTH:
+ {
+ if (sectorLen != 8) {
- }
}
- break;
- case DP_TYPE_RAW_DDS238Packet:
- {
- if (sectorLen != 15) {
+ else {
+ year = data[ofs + 4];
+ month = data[ofs + 4 + 1];
+ // consumption
+ iVal = data[ofs + 6 + 4] << 8 | data[ofs + 7 + 4];
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "DP_TYPE_RAW_TAC2121C_LASTMONTH: month %i, year %i, val %i\n",
+ month, year, iVal);
- } else {
- // FREQ??
- iVal = data[ofs + 8 + 4] << 8 | data[ofs + 9 + 4];
- //CHANNEL_SetAllChannelsByType(QQQQQQ, iVal);
- // 06 46 = 1606 => A x 100? ?
- iVal = data[ofs + 11 + 4] << 8 | data[ofs + 12 + 4];
- CHANNEL_SetAllChannelsByType(ChType_Current_div1000, iVal);
- // Voltage?
- iVal = data[ofs + 13 + 4] << 8 | data[ofs + 14 + 4];
- CHANNEL_SetAllChannelsByType(ChType_Voltage_div10, iVal);
- }
}
- break;
+ }
+ break;
+ case DP_TYPE_RAW_TAC2121C_VCP:
+ {
+ if (sectorLen == 8 || sectorLen == 10) {
+ // voltage
+ iVal = data[ofs + 0 + 4] << 8 | data[ofs + 1 + 4];
+ CHANNEL_SetAllChannelsByType(ChType_Voltage_div10, iVal);
+ // current
+ iVal = data[ofs + 3 + 4] << 8 | data[ofs + 4 + 4];
+ CHANNEL_SetAllChannelsByType(ChType_Current_div1000, iVal);
+ // power
+ iVal = data[ofs + 6 + 4] << 8 | data[ofs + 7 + 4];
+ CHANNEL_SetAllChannelsByType(ChType_Power, iVal);
+ }
+ else {
+
+ }
+ }
+ break;
+ case DP_TYPE_RAW_DDS238Packet:
+ {
+ if (sectorLen != 15) {
+
+ }
+ else {
+ // FREQ??
+ iVal = data[ofs + 8 + 4] << 8 | data[ofs + 9 + 4];
+ //CHANNEL_SetAllChannelsByType(QQQQQQ, iVal);
+ // 06 46 = 1606 => A x 100? ?
+ iVal = data[ofs + 11 + 4] << 8 | data[ofs + 12 + 4];
+ CHANNEL_SetAllChannelsByType(ChType_Current_div1000, iVal);
+ // Voltage?
+ iVal = data[ofs + 13 + 4] << 8 | data[ofs + 14 + 4];
+ CHANNEL_SetAllChannelsByType(ChType_Voltage_div10, iVal);
+ }
+ }
+ break;
}
}
}
- // 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
@@ -1108,157 +1121,159 @@ void TuyaMCU_ParseStateMessage(const byte *data, int len) {
#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;
+void TuyaMCU_ProcessIncoming(const byte* data, int len) {
+ 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_HEARTBEAT:
- heartbeat_valid = true;
- heartbeat_counter = 0;
- break;
- case TUYA_CMD_MCU_CONF:
- working_mode_valid = true;
- int dataCount;
- // https://github.com/openshwprojects/OpenBK7231T_App/issues/291
- // header ver TUYA_CMD_MCU_CONF LENGHT Chksum
- // Pushing
- // 55 AA 01 02 00 03 FF 01 01 06
- // 55 AA 01 02 00 03 FF 01 00 05
- // Rotating down
- // 55 AA 01 02 00 05 01 24 02 01 0A 39
- // 55 AA 01 02 00 03 01 09 00 0F
- // Rotating up
- // 55 AA 01 02 00 05 01 24 01 01 0A 38
- // 55 AA 01 02 00 03 01 09 01 10
- dataCount = data[5];
- if (dataCount == 0)
- {
- self_processing_mode = true;
- }
- else if (dataCount == 2)
- {
- self_processing_mode = false;
- }
- if(5 + dataCount + 2 != len) {
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming: TUYA_CMD_MCU_CONF had wrong data lenght?");
- } else {
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming: TUYA_CMD_MCU_CONF, TODO!");
- }
- break;
- case TUYA_CMD_WIFI_STATE:
- wifi_state_valid = true;
- break;
+ 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;
+ int dataCount;
+ // https://github.com/openshwprojects/OpenBK7231T_App/issues/291
+ // header ver TUYA_CMD_MCU_CONF LENGHT Chksum
+ // Pushing
+ // 55 AA 01 02 00 03 FF 01 01 06
+ // 55 AA 01 02 00 03 FF 01 00 05
+ // Rotating down
+ // 55 AA 01 02 00 05 01 24 02 01 0A 39
+ // 55 AA 01 02 00 03 01 09 00 0F
+ // Rotating up
+ // 55 AA 01 02 00 05 01 24 01 01 0A 38
+ // 55 AA 01 02 00 03 01 09 01 10
+ dataCount = data[5];
+ if (dataCount == 0)
+ {
+ self_processing_mode = true;
+ }
+ else if (dataCount == 2)
+ {
+ self_processing_mode = false;
+ }
+ if (5 + dataCount + 2 != len) {
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "TuyaMCU_ProcessIncoming: TUYA_CMD_MCU_CONF had wrong data lenght?");
+ }
+ else {
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "TuyaMCU_ProcessIncoming: TUYA_CMD_MCU_CONF, TODO!");
+ }
+ break;
+ case TUYA_CMD_WIFI_STATE:
+ wifi_state_valid = true;
+ break;
- case TUYA_CMD_STATE:
- TuyaMCU_ParseStateMessage(data+6,len-6);
- state_updated = true;
- g_sendQueryStatePackets = 0;
- 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"}$
- // uartFakeHex 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
- // This packet includes first a DateTime, then RealTimeDataStorage
- TuyaMCU_V0_ParseRealTimeWithRecordStorage(data+6,len-6, true);
- } else {
-
- }
- break;
- case 0x05:
- // This was added for this user:
- // https://www.elektroda.com/rtvforum/topic3937723.html
- if (version == 0) {
- // 0x05 packet for version 0 (not 0x03) of TuyaMCU
- // This packet has no datetime stamp
- TuyaMCU_V0_ParseRealTimeWithRecordStorage(data + 6, len - 6, false);
- }
- else {
- }
- break;
- case TUYA_CMD_WEATHERDATA:
- TuyaMCU_ParseWeatherData(data + 6, len - 6);
- break;
+ case TUYA_CMD_STATE:
+ TuyaMCU_ParseStateMessage(data + 6, len - 6);
+ state_updated = true;
+ g_sendQueryStatePackets = 0;
+ 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"}$
+ // uartFakeHex 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
+ // This packet includes first a DateTime, then RealTimeDataStorage
+ TuyaMCU_V0_ParseRealTimeWithRecordStorage(data + 6, len - 6, true);
+ }
+ else {
- case TUYA_CMD_SET_RSSI:
- // This is send by TH06, S09
- // Info:TuyaMCU:TUYAMCU received: 55 AA 03 24 00 00 26
- if (version == 3) {
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming: received TUYA_CMD_SET_RSSI, so sending back signal strength");
- TuyaMCU_Send_RSSI(HAL_GetWifiStrength());
- }
- break;
+ }
+ break;
+ case 0x05:
+ // This was added for this user:
+ // https://www.elektroda.com/rtvforum/topic3937723.html
+ if (version == 0) {
+ // 0x05 packet for version 0 (not 0x03) of TuyaMCU
+ // This packet has no datetime stamp
+ TuyaMCU_V0_ParseRealTimeWithRecordStorage(data + 6, len - 6, false);
+ }
+ else {
+ }
+ break;
+ case TUYA_CMD_WEATHERDATA:
+ TuyaMCU_ParseWeatherData(data + 6, len - 6);
+ break;
- case TUYA_CMD_NETWORK_STATUS:
- //This is sent by S09
- //Info:TuyaMCU:TUYAMCU received: 55 AA 03 2B 00 00 2D
- //
- if (version == 3 ){
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming: (test for S09 calendar/IR device) received TUYA_CMD_NETWORK_STATUS 0x2B ");
- TuyaMCU_SendNetworkStatus();
- }
- break;
- default:
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_ProcessIncoming: unhandled type %i",cmd);
- break;
- }
- EventHandlers_FireEvent(CMD_EVENT_TUYAMCU_PARSED, cmd);
+ case TUYA_CMD_SET_RSSI:
+ // This is send by TH06, S09
+ // Info:TuyaMCU:TUYAMCU received: 55 AA 03 24 00 00 26
+ if (version == 3) {
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "TuyaMCU_ProcessIncoming: received TUYA_CMD_SET_RSSI, so sending back signal strength");
+ TuyaMCU_Send_RSSI(HAL_GetWifiStrength());
+ }
+ break;
+
+ case TUYA_CMD_NETWORK_STATUS:
+ //This is sent by S09
+ //Info:TuyaMCU:TUYAMCU received: 55 AA 03 2B 00 00 2D
+ //
+ if (version == 3) {
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "TuyaMCU_ProcessIncoming: (test for S09 calendar/IR device) received TUYA_CMD_NETWORK_STATUS 0x2B ");
+ TuyaMCU_SendNetworkStatus();
+ }
+ break;
+ default:
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "TuyaMCU_ProcessIncoming: unhandled type %i", cmd);
+ break;
+ }
+ EventHandlers_FireEvent(CMD_EVENT_TUYAMCU_PARSED, cmd);
}
-commandResult_t 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 CMD_RES_NOT_ENOUGH_ARGUMENTS;
- }
- while(*args) {
- byte b;
- b = hexbyte(args);
+commandResult_t 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 CMD_RES_NOT_ENOUGH_ARGUMENTS;
+ }
+ while (*args) {
+ byte b;
+ b = hexbyte(args);
- if(sizeof(packet)>c+1) {
- packet[c] = b;
- c++;
- }
- args += 2;
- }
- TuyaMCU_ProcessIncoming(packet,c);
- return CMD_RES_OK;
+ if (sizeof(packet) > c + 1) {
+ packet[c] = b;
+ c++;
+ }
+ args += 2;
+ }
+ TuyaMCU_ProcessIncoming(packet, c);
+ return CMD_RES_OK;
}
void TuyaMCU_RunWiFiUpdateAndPackets() {
//addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU,"TuyaMCU_WifiCheck %d ", wifi_state_timer);
@@ -1295,99 +1310,102 @@ void TuyaMCU_RunWiFiUpdateAndPackets() {
}
}
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);
// extraDebug log level
- addLogAdv(LOG_EXTRADEBUG, LOG_FEATURE_TUYAMCU,"TuyaMCU heartbeat_valid = %i, product_information_valid=%i,"
+ addLogAdv(LOG_EXTRADEBUG, LOG_FEATURE_TUYAMCU, "TuyaMCU heartbeat_valid = %i, product_information_valid=%i,"
" self_processing_mode = %i, wifi_state_valid = %i, wifi_state_timer=%i\n",
- (int)heartbeat_valid,(int)product_information_valid,(int)self_processing_mode,
- (int)wifi_state_valid,(int)wifi_state_timer);
-
- while (1)
- {
- len = UART_TryToGetNextTuyaPacket(data,sizeof(data));
- if(len > 0) {
- buffer_for_log[0] = 0;
- for(i = 0; i < len; i++) {
- snprintf(buffer2, sizeof(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);
+ (int)heartbeat_valid, (int)product_information_valid, (int)self_processing_mode,
+ (int)wifi_state_valid, (int)wifi_state_timer);
+
+ while (1)
+ {
+ len = UART_TryToGetNextTuyaPacket(data, sizeof(data));
+ if (len > 0) {
+ buffer_for_log[0] = 0;
+ for (i = 0; i < len; i++) {
+ snprintf(buffer2, sizeof(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);
#if 1
// redo sprintf without spaces
- buffer_for_log[0] = 0;
- for(i = 0; i < len; i++) {
- snprintf(buffer2, sizeof(buffer2),"%02X",data[i]);
- strcat_safe(buffer_for_log,buffer2,sizeof(buffer_for_log));
- }
+ buffer_for_log[0] = 0;
+ for (i = 0; i < len; i++) {
+ snprintf(buffer2, sizeof(buffer2), "%02X", data[i]);
+ strcat_safe(buffer_for_log, buffer2, sizeof(buffer_for_log));
+ }
// fire string event, as we already have it sprintfed
// This is so we can have event handlers that fire
// when an UART string is received...
- EventHandlers_FireEvent_String(CMD_EVENT_ON_UART,buffer_for_log);
+ EventHandlers_FireEvent_String(CMD_EVENT_ON_UART, buffer_for_log);
#endif
- TuyaMCU_ProcessIncoming(data,len);
- } else {
- break;
- }
- }
+ TuyaMCU_ProcessIncoming(data, len);
+ }
+ else {
+ break;
+ }
+ }
- /* Command controll */
- if (heartbeat_timer == 0)
- {
- /* Generate heartbeat to keep communication alove */
- TuyaMCU_SendCommandWithData(TUYA_CMD_HEARTBEAT, NULL, 0);
- heartbeat_timer = 3;
- heartbeat_counter++;
- if (heartbeat_counter>=4)
- {
- /* unanswerred heartbeats -> lost communication */
- heartbeat_valid = false;
- product_information_valid = false;
- working_mode_valid = false;
- wifi_state_valid = false;
- state_updated = false;
+ /* Command controll */
+ if (heartbeat_timer == 0)
+ {
+ /* Generate heartbeat to keep communication alove */
+ TuyaMCU_SendCommandWithData(TUYA_CMD_HEARTBEAT, NULL, 0);
+ heartbeat_timer = 3;
+ heartbeat_counter++;
+ if (heartbeat_counter >= 4)
+ {
+ /* unanswerred heartbeats -> lost communication */
+ heartbeat_valid = false;
+ product_information_valid = false;
+ working_mode_valid = false;
+ wifi_state_valid = false;
+ state_updated = false;
g_sendQueryStatePackets = 0;
- }
- //addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "WFS: %d H%d P%d M%d W%d S%d", wifi_state_timer,
- // heartbeat_valid, product_information_valid, working_mode_valid, wifi_state_valid,
- // state_updated);
- } else {
- /* Heartbeat timer - sent every 3 seconds */
- if (heartbeat_timer>0)
- {
- heartbeat_timer--;
- } else {
- heartbeat_timer = 0;
- }
- if (heartbeat_valid == true && DRV_IsRunning("tmSensor")==false)
- {
- /* Connection Active */
- if (product_information_valid == false)
- {
+ }
+ //addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "WFS: %d H%d P%d M%d W%d S%d", wifi_state_timer,
+ // heartbeat_valid, product_information_valid, working_mode_valid, wifi_state_valid,
+ // state_updated);
+ }
+ else {
+ /* Heartbeat timer - sent every 3 seconds */
+ if (heartbeat_timer > 0)
+ {
+ heartbeat_timer--;
+ }
+ else {
+ heartbeat_timer = 0;
+ }
+ if (heartbeat_valid == true && DRV_IsRunning("tmSensor") == false)
+ {
+ /* Connection Active */
+ if (product_information_valid == false)
+ {
addLogAdv(LOG_EXTRADEBUG, LOG_FEATURE_TUYAMCU, "Will send TUYA_CMD_QUERY_PRODUCT.\n");
- /* Request production information */
- TuyaMCU_SendCommandWithData(TUYA_CMD_QUERY_PRODUCT, NULL, 0);
- }
- else if (working_mode_valid == false)
- {
+ /* Request production information */
+ TuyaMCU_SendCommandWithData(TUYA_CMD_QUERY_PRODUCT, NULL, 0);
+ }
+ else if (working_mode_valid == false)
+ {
addLogAdv(LOG_EXTRADEBUG, LOG_FEATURE_TUYAMCU, "Will send TUYA_CMD_MCU_CONF.\n");
- /* Request working mode */
- TuyaMCU_SendCommandWithData(TUYA_CMD_MCU_CONF, NULL, 0);
- }
- else if ((wifi_state_valid == false) && (self_processing_mode == false))
- {
- /* Reset wifi state -> Aquirring network connection */
- Tuya_SetWifiState(g_defaultTuyaMCUWiFiState);
+ /* Request working mode */
+ TuyaMCU_SendCommandWithData(TUYA_CMD_MCU_CONF, NULL, 0);
+ }
+ else if ((wifi_state_valid == false) && (self_processing_mode == false))
+ {
+ /* Reset wifi state -> Aquirring network connection */
+ Tuya_SetWifiState(g_defaultTuyaMCUWiFiState);
addLogAdv(LOG_EXTRADEBUG, LOG_FEATURE_TUYAMCU, "Will send TUYA_CMD_WIFI_STATE.\n");
- TuyaMCU_SendCommandWithData(TUYA_CMD_WIFI_STATE, NULL, 0);
- }
- else if (state_updated == false)
- {
+ TuyaMCU_SendCommandWithData(TUYA_CMD_WIFI_STATE, NULL, 0);
+ }
+ else if (state_updated == false)
+ {
// fix for this device getting stuck?
// https://www.elektroda.com/rtvforum/topic3936455.html
if (g_sendQueryStatePackets > 1 && (g_sendQueryStatePackets % 2 == 0)) {
@@ -1397,21 +1415,21 @@ void TuyaMCU_RunFrame() {
/* Request first state of all DP - this should list all existing DP */
addLogAdv(LOG_EXTRADEBUG, LOG_FEATURE_TUYAMCU, "Will send TUYA_CMD_QUERY_STATE (state_updated==false, try %i).\n",
g_sendQueryStatePackets);
- TuyaMCU_SendCommandWithData(TUYA_CMD_QUERY_STATE, NULL, 0);
+ TuyaMCU_SendCommandWithData(TUYA_CMD_QUERY_STATE, NULL, 0);
}
g_sendQueryStatePackets++;
- }
- else
- {
+ }
+ else
+ {
TuyaMCU_RunWiFiUpdateAndPackets();
- }
- }
- }
+ }
+ }
+ }
}
-commandResult_t TuyaMCU_SetBaudRate(const void *context, const char *cmd, const char *args, int cmdFlags) {
- Tokenizer_TokenizeString(args,0);
+commandResult_t TuyaMCU_SetBaudRate(const void* context, const char* cmd, const char* args, int cmdFlags) {
+ Tokenizer_TokenizeString(args, 0);
// following check must be done after 'Tokenizer_TokenizeString',
// so we know arguments count in Tokenizer. 'cmd' argument is
// only for warning display
@@ -1419,73 +1437,73 @@ commandResult_t TuyaMCU_SetBaudRate(const void *context, const char *cmd, const
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
}
- g_baudRate = Tokenizer_GetArgInteger(0);
-
- return CMD_RES_OK;
+ g_baudRate = Tokenizer_GetArgInteger(0);
+
+ return CMD_RES_OK;
}
void TuyaMCU_Init()
{
- UART_InitUART(g_baudRate);
- UART_InitReceiveRingBuffer(256);
- // uartSendHex 55AA0008000007
+ UART_InitUART(g_baudRate);
+ UART_InitReceiveRingBuffer(256);
+ // uartSendHex 55AA0008000007
//cmddetail:{"name":"tuyaMcu_testSendTime","args":"",
//cmddetail:"descr":"Sends a example date by TuyaMCU to clock/callendar MCU",
//cmddetail:"fn":"TuyaMCU_Send_SetTime_Example","file":"driver/drv_tuyaMCU.c","requires":"",
//cmddetail:"examples":""}
- CMD_RegisterCommand("tuyaMcu_testSendTime", TuyaMCU_Send_SetTime_Example, NULL);
+ CMD_RegisterCommand("tuyaMcu_testSendTime", TuyaMCU_Send_SetTime_Example, NULL);
//cmddetail:{"name":"tuyaMcu_sendCurTime","args":"",
//cmddetail:"descr":"Sends a current date by TuyaMCU to clock/callendar MCU. Time is taken from NTP driver, so NTP also should be already running.",
//cmddetail:"fn":"TuyaMCU_Send_SetTime_Current","file":"driver/drv_tuyaMCU.c","requires":"",
//cmddetail:"examples":""}
- CMD_RegisterCommand("tuyaMcu_sendCurTime", TuyaMCU_Send_SetTime_Current, 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("tuyaMcu_sendCurTime", TuyaMCU_Send_SetTime_Current, NULL);
+ ///CMD_RegisterCommand("tuyaMcu_sendSimple","",TuyaMCU_Send_Simple, "Appends a 0x55 0xAA header to a data, append a checksum at end and send");
//cmddetail:{"name":"linkTuyaMCUOutputToChannel","args":"[dpId][varType][channelID]",
//cmddetail:"descr":"Used to map between TuyaMCU dpIDs and our internal channels. 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",
//cmddetail:"fn":"TuyaMCU_LinkTuyaMCUOutputToChannel","file":"driver/drv_tuyaMCU.c","requires":"",
//cmddetail:"examples":""}
- CMD_RegisterCommand("linkTuyaMCUOutputToChannel", TuyaMCU_LinkTuyaMCUOutputToChannel, NULL);
+ CMD_RegisterCommand("linkTuyaMCUOutputToChannel", TuyaMCU_LinkTuyaMCUOutputToChannel, NULL);
//cmddetail:{"name":"tuyaMcu_setDimmerRange","args":"[Min][Max]",
//cmddetail:"descr":"Set dimmer range used by TuyaMCU",
//cmddetail:"fn":"TuyaMCU_SetDimmerRange","file":"driver/drv_tuyaMCU.c","requires":"",
//cmddetail:"examples":""}
- CMD_RegisterCommand("tuyaMcu_setDimmerRange", TuyaMCU_SetDimmerRange, NULL);
+ CMD_RegisterCommand("tuyaMcu_setDimmerRange", TuyaMCU_SetDimmerRange, NULL);
//cmddetail:{"name":"tuyaMcu_sendHeartbeat","args":"",
//cmddetail:"descr":"Send heartbeat to TuyaMCU",
//cmddetail:"fn":"TuyaMCU_SendHeartbeat","file":"driver/drv_tuyaMCU.c","requires":"",
//cmddetail:"examples":""}
- CMD_RegisterCommand("tuyaMcu_sendHeartbeat", TuyaMCU_SendHeartbeat, NULL);
+ CMD_RegisterCommand("tuyaMcu_sendHeartbeat", TuyaMCU_SendHeartbeat, NULL);
//cmddetail:{"name":"tuyaMcu_sendQueryState","args":"",
//cmddetail:"descr":"Send query state command. No arguments needed.",
//cmddetail:"fn":"TuyaMCU_SendQueryState","file":"driver/drv_tuyaMCU.c","requires":"",
//cmddetail:"examples":""}
- CMD_RegisterCommand("tuyaMcu_sendQueryState", TuyaMCU_SendQueryState, NULL);
+ CMD_RegisterCommand("tuyaMcu_sendQueryState", TuyaMCU_SendQueryState, NULL);
//cmddetail:{"name":"tuyaMcu_sendProductInformation","args":"",
//cmddetail:"descr":"Send query packet (0x01). No arguments needed.",
//cmddetail:"fn":"TuyaMCU_SendQueryProductInformation","file":"driver/drv_tuyaMCU.c","requires":"",
//cmddetail:"examples":""}
- CMD_RegisterCommand("tuyaMcu_sendProductInformation", TuyaMCU_SendQueryProductInformation, NULL);
+ CMD_RegisterCommand("tuyaMcu_sendProductInformation", TuyaMCU_SendQueryProductInformation, NULL);
//cmddetail:{"name":"tuyaMcu_sendState","args":"[dpID][dpType][dpValue]",
//cmddetail:"descr":"Manually send set state command. Do not use it. Use mapping, so communication is bidirectional and automatic.",
//cmddetail:"fn":"TuyaMCU_SendStateCmd","file":"driver/drv_tuyaMCU.c","requires":"",
//cmddetail:"examples":""}
- CMD_RegisterCommand("tuyaMcu_sendState", TuyaMCU_SendStateCmd, NULL);
+ CMD_RegisterCommand("tuyaMcu_sendState", TuyaMCU_SendStateCmd, NULL);
//cmddetail:{"name":"tuyaMcu_sendMCUConf","args":"",
//cmddetail:"descr":"Send MCU conf command",
//cmddetail:"fn":"TuyaMCU_SendMCUConf","file":"driver/drv_tuyaMCU.c","requires":"",
//cmddetail:"examples":""}
- CMD_RegisterCommand("tuyaMcu_sendMCUConf", TuyaMCU_SendMCUConf, NULL);
+ CMD_RegisterCommand("tuyaMcu_sendMCUConf", TuyaMCU_SendMCUConf, NULL);
//cmddetail:{"name":"fakeTuyaPacket","args":"[HexString]",
//cmddetail:"descr":"This simulates packet being sent from TuyaMCU to our OBK device.",
//cmddetail:"fn":"TuyaMCU_FakePacket","file":"driver/drv_tuyaMCU.c","requires":"",
//cmddetail:"examples":""}
- CMD_RegisterCommand("fakeTuyaPacket",TuyaMCU_FakePacket, NULL);
+ CMD_RegisterCommand("fakeTuyaPacket", TuyaMCU_FakePacket, NULL);
//cmddetail:{"name":"tuyaMcu_setBaudRate","args":"[BaudValue]",
//cmddetail:"descr":"Sets the baud rate used by TuyaMCU UART communication. Default value is 9600. Some other devices require 115200.",
//cmddetail:"fn":"TuyaMCU_SetBaudRate","file":"driver/drv_tuyaMCU.c","requires":"",
//cmddetail:"examples":""}
- CMD_RegisterCommand("tuyaMcu_setBaudRate",TuyaMCU_SetBaudRate, NULL);
+ CMD_RegisterCommand("tuyaMcu_setBaudRate", TuyaMCU_SetBaudRate, NULL);
//cmddetail:{"name":"tuyaMcu_sendRSSI","args":"",
//cmddetail:"descr":"Command sends the specific RSSI value to TuyaMCU (it will send current RSSI if no argument is set)",
//cmddetail:"fn":"Cmd_TuyaMCU_Send_RSSI","file":"driver/drv_tuyaMCU.c","requires":"",
diff --git a/src/httpserver/hass.c b/src/httpserver/hass.c
index e840d6b24..ff8ed46e5 100644
--- a/src/httpserver/hass.c
+++ b/src/httpserver/hass.c
@@ -58,6 +58,12 @@ void hass_populate_unique_id(ENTITY_TYPE type, int index, char* uniq_id) {
case HUMIDITY_SENSOR:
sprintf(uniq_id, "%s_%s_%d", longDeviceName, "humidity", index);
break;
+ case CO2_SENSOR:
+ sprintf(uniq_id, "%s_%s_%d", longDeviceName, "co2", index);
+ break;
+ case TVOC_SENSOR:
+ sprintf(uniq_id, "%s_%s_%d", longDeviceName, "tvoc", index);
+ break;
case BATTERY_SENSOR:
sprintf(uniq_id, "%s_%s_%d", longDeviceName, "battery", index);
break;
@@ -96,6 +102,8 @@ void hass_populate_device_config_channel(ENTITY_TYPE type, char* uniq_id, HassDe
sprintf(info->channel, "switch/%s/config", uniq_id);
break;
+ case CO2_SENSOR:
+ case TVOC_SENSOR:
case POWER_SENSOR:
case BATTERY_SENSOR:
case BATTERY_VOLTAGE_SENSOR:
@@ -186,6 +194,14 @@ HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, char* payload
isSensor = true;
sprintf(g_hassBuffer, "%s Humidity", CFG_GetShortDeviceName());
break;
+ case CO2_SENSOR:
+ isSensor = true;
+ sprintf(g_hassBuffer, "%s CO2", CFG_GetShortDeviceName());
+ break;
+ case TVOC_SENSOR:
+ isSensor = true;
+ sprintf(g_hassBuffer, "%s Tvoc", CFG_GetShortDeviceName());
+ break;
case BATTERY_SENSOR:
isSensor = true;
sprintf(g_hassBuffer, "%s Battery", CFG_GetShortDeviceName());
@@ -282,10 +298,10 @@ HassDeviceInfo* hass_init_light_device_info(ENTITY_TYPE type) {
cJSON_AddStringToObject(info->root, "clr_temp_cmd_t", g_hassBuffer); //color_temp_command_topic
cJSON_AddStringToObject(info->root, "clr_temp_stat_t", "~/led_temperature/get"); //color_temp_state_topic
-
+
sprintf(g_hassBuffer, "%.0f", led_temperature_min);
cJSON_AddStringToObject(info->root, "min_mirs", g_hassBuffer); //min_mireds
-
+
sprintf(g_hassBuffer, "%.0f", led_temperature_max);
cJSON_AddStringToObject(info->root, "max_mirs", g_hassBuffer); //max_mireds
}
@@ -381,6 +397,18 @@ HassDeviceInfo* hass_init_sensor_device_info(ENTITY_TYPE type, int channel) {
sprintf(g_hassBuffer, "~/%d/get", channel);
cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer);
break;
+ case CO2_SENSOR:
+ cJSON_AddStringToObject(info->root, "dev_cla", "carbon_dioxide");
+ cJSON_AddStringToObject(info->root, "unit_of_meas", "ppm");
+ sprintf(g_hassBuffer, "~/%d/get", channel);
+ cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer);
+ break;
+ case TVOC_SENSOR:
+ cJSON_AddStringToObject(info->root, "dev_cla", "volatile_organic_compounds");
+ cJSON_AddStringToObject(info->root, "unit_of_meas", "ppb");
+ sprintf(g_hassBuffer, "~/%d/get", channel);
+ cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer);
+ break;
case BATTERY_SENSOR:
cJSON_AddStringToObject(info->root, "dev_cla", "battery");
cJSON_AddStringToObject(info->root, "unit_of_meas", "%");
diff --git a/src/httpserver/hass.h b/src/httpserver/hass.h
index c5bf079c2..d1d8eb197 100644
--- a/src/httpserver/hass.h
+++ b/src/httpserver/hass.h
@@ -38,7 +38,12 @@ typedef enum {
/// @brief Battery level sensor in perc
BATTERY_SENSOR,
/// @brief Battery votage sensor in mV
- BATTERY_VOLTAGE_SENSOR
+ BATTERY_VOLTAGE_SENSOR,
+
+ /// @brief CO2 sensor in ppm
+ CO2_SENSOR,
+ /// @brief TVOC sensor in ppb
+ TVOC_SENSOR
} ENTITY_TYPE;
diff --git a/src/httpserver/http_fns.c b/src/httpserver/http_fns.c
index 872542b07..40606c4ef 100644
--- a/src/httpserver/http_fns.c
+++ b/src/httpserver/http_fns.c
@@ -1665,6 +1665,17 @@ void doHomeAssistantDiscovery(const char* topic, http_request_t* request) {
MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN);
hass_free_device_info(dev_info);
+ discoveryQueued = true;
+ }
+ else if (IS_PIN_AIR_SENSOR_ROLE(g_cfg.pins.roles[i])) {
+ dev_info = hass_init_sensor_device_info(CO2_SENSOR, PIN_GetPinChannelForPinIndex(i));
+ MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN);
+ hass_free_device_info(dev_info);
+
+ dev_info = hass_init_sensor_device_info(TVOC_SENSOR, PIN_GetPinChannel2ForPinIndex(i));
+ MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN);
+ hass_free_device_info(dev_info);
+
discoveryQueued = true;
}
}
@@ -2109,7 +2120,7 @@ int http_fn_cfg_pins(http_request_t* request) {
poststr(request, "");
// Primary linked channel
// Some roles do not need any channels
- if ((si != IOR_SHT3X_CLK && si != IOR_CHT8305_CLK && si != IOR_Button_ToggleAll && si != IOR_Button_ToggleAll_n
+ if ((si != IOR_SGP_CLK && si != IOR_SHT3X_CLK && si != IOR_CHT8305_CLK && si != IOR_Button_ToggleAll && si != IOR_Button_ToggleAll_n
&& si != IOR_BL0937_CF && si != IOR_BL0937_CF1 && si != IOR_BL0937_SEL
&& si != IOR_LED_WIFI && si != IOR_LED_WIFI_n && si != IOR_LED_WIFI_n
&& !(si >= IOR_IRRecv && si <= IOR_DHT11)
@@ -2120,7 +2131,7 @@ int http_fn_cfg_pins(http_request_t* request) {
}
// Secondary linked channel
// For button, is relay index to toggle on double click
- if (si == IOR_Button || si == IOR_Button_n || IS_PIN_DHT_ROLE(si) || IS_PIN_TEMP_HUM_SENSOR_ROLE(si))
+ if (si == IOR_Button || si == IOR_Button_n || IS_PIN_DHT_ROLE(si) || IS_PIN_TEMP_HUM_SENSOR_ROLE(si) || IS_PIN_AIR_SENSOR_ROLE(si))
{
hprintf255(request, "", i, ch2);
}
diff --git a/src/httpserver/json_interface.c b/src/httpserver/json_interface.c
index 16034b921..7f74c95fe 100644
--- a/src/httpserver/json_interface.c
+++ b/src/httpserver/json_interface.c
@@ -21,19 +21,19 @@
#include "../driver/drv_local.h"
#include "../driver/drv_bl_shared.h"
-void JSON_PrintKeyValue_String(void* request, jsonCb_t printer, const char *key, const char *value, bool bComma) {
+void JSON_PrintKeyValue_String(void* request, jsonCb_t printer, const char* key, const char* value, bool bComma) {
printer(request, "\"%s\":\"%s\"", key, value);
if (bComma) {
printer(request, ",");
}
}
-void JSON_PrintKeyValue_Int(void* request, jsonCb_t printer, const char *key, int value, bool bComma) {
+void JSON_PrintKeyValue_Int(void* request, jsonCb_t printer, const char* key, int value, bool bComma) {
printer(request, "\"%s\":%i", key, value);
if (bComma) {
printer(request, ",");
}
}
-void JSON_PrintKeyValue_Float(void* request, jsonCb_t printer, const char *key, float value, bool bComma) {
+void JSON_PrintKeyValue_Float(void* request, jsonCb_t printer, const char* key, float value, bool bComma) {
printer(request, "\"%s\":%f", key, value);
if (bComma) {
printer(request, ",");
@@ -117,10 +117,10 @@ static int http_tasmota_json_power(void* request, jsonCb_t printer) {
// it looks like they include C and W in color
if (LED_IsLedDriverChipRunning() || numPWMs == 5) {
- sprintf(buff32, "%i,%i,%i,%i,%i",(int)rgbcw[0], (int)rgbcw[1], (int)rgbcw[2], (int)rgbcw[3], (int)rgbcw[4]);
+ sprintf(buff32, "%i,%i,%i,%i,%i", (int)rgbcw[0], (int)rgbcw[1], (int)rgbcw[2], (int)rgbcw[3], (int)rgbcw[4]);
}
else {
- sprintf(buff32,"%i,%i,%i", (int)rgbcw[0], (int)rgbcw[1], (int)rgbcw[2]);
+ sprintf(buff32, "%i,%i,%i", (int)rgbcw[0], (int)rgbcw[1], (int)rgbcw[2]);
}
JSON_PrintKeyValue_String(request, printer, "Color", buff32, true);
sprintf(buff32, "%i,%i,%i", (int)hsv[0], (int)hsv[1], (int)hsv[2]);
@@ -260,7 +260,7 @@ static int http_tasmota_json_ENERGY(void* request, jsonCb_t printer) {
}
*/
static int http_tasmota_json_SENSOR(void* request, jsonCb_t printer) {
- float temperature, humidity;
+ float chan_val1, chan_val2;
int channel_1, channel_2, g_pin_1 = 0;
printer(request, ",");
if (DRV_IsRunning("SHT3X")) {
@@ -268,15 +268,15 @@ static int http_tasmota_json_SENSOR(void* request, jsonCb_t printer) {
channel_1 = g_cfg.pins.channels[g_pin_1];
channel_2 = g_cfg.pins.channels2[g_pin_1];
- temperature = CHANNEL_GetFloat(channel_1) / 10.0f;
- humidity = CHANNEL_GetFloat(channel_2);
+ chan_val1 = CHANNEL_GetFloat(channel_1) / 10.0f;
+ chan_val2 = CHANNEL_GetFloat(channel_2);
// writer header
printer(request, "\"SHT3X\":");
// following check will clear NaN values
printer(request, "{");
- printer(request, "\"Temperature\": %.1f,", temperature);
- printer(request, "\"Humidity\": %.0f", humidity);
+ printer(request, "\"Temperature\": %.1f,", chan_val1);
+ printer(request, "\"Humidity\": %.0f", chan_val2);
// close ENERGY block
printer(request, "},");
}
@@ -285,15 +285,32 @@ static int http_tasmota_json_SENSOR(void* request, jsonCb_t printer) {
channel_1 = g_cfg.pins.channels[g_pin_1];
channel_2 = g_cfg.pins.channels2[g_pin_1];
- temperature = CHANNEL_GetFloat(channel_1) / 10.0f;
- humidity = CHANNEL_GetFloat(channel_2);
+ chan_val1 = CHANNEL_GetFloat(channel_1) / 10.0f;
+ chan_val2 = CHANNEL_GetFloat(channel_2);
// writer header
printer(request, "\"CHT8305\":");
// following check will clear NaN values
printer(request, "{");
- printer(request, "\"Temperature\": %.1f,", temperature);
- printer(request, "\"Humidity\": %.0f", humidity);
+ printer(request, "\"Temperature\": %.1f,", chan_val1);
+ printer(request, "\"Humidity\": %.0f", chan_val2);
+ // close ENERGY block
+ printer(request, "},");
+ }
+ if (DRV_IsRunning("SGP")) {
+ g_pin_1 = PIN_FindPinIndexForRole(IOR_SGP_DAT, g_pin_1);
+ channel_1 = g_cfg.pins.channels[g_pin_1];
+ channel_2 = g_cfg.pins.channels2[g_pin_1];
+
+ chan_val1 = CHANNEL_GetFloat(channel_1);
+ chan_val2 = CHANNEL_GetFloat(channel_2);
+
+ // writer header
+ printer(request, "\"SGP\":");
+ // following check will clear NaN values
+ printer(request, "{");
+ printer(request, "\"CO2\": %.0f,", chan_val1);
+ printer(request, "\"Tvoc\": %.0f", chan_val2);
// close ENERGY block
printer(request, "},");
}
@@ -978,7 +995,7 @@ int JSON_ProcessCommandReply(const char* cmd, const char* arg, void* request, js
}
else if (!wal_strnicmp(cmd, "SSID1", 5)) {
printer(request, "{");
- JSON_PrintKeyValue_String(request,printer,"SSID1", CFG_GetWiFiSSID(),false);
+ JSON_PrintKeyValue_String(request, printer, "SSID1", CFG_GetWiFiSSID(), false);
printer(request, "}");
}
else if (!wal_strnicmp(cmd, "LED_Map", 7)) {
diff --git a/src/httpserver/new_http.c b/src/httpserver/new_http.c
index b9a78305d..e95cc8b37 100644
--- a/src/httpserver/new_http.c
+++ b/src/httpserver/new_http.c
@@ -448,8 +448,9 @@ const char* htmlPinRoleNames[] = {
"TM1637_DIO",
"TM1637_CLK",
"BL0937SEL_n",
- "DoorSnsrWSleep_pd",
- "error",
+ "DoorSnsrWSleep_pd",
+ "SGP_CLK",
+ "SGP_DAT",
"error",
"error",
"error",
diff --git a/src/new_pins.c b/src/new_pins.c
index 168a83ceb..02932d563 100644
--- a/src/new_pins.c
+++ b/src/new_pins.c
@@ -940,7 +940,7 @@ static void Channel_OnChanged(int ch, int prevValue, int iFlags) {
}
if ((iFlags & CHANNEL_SET_FLAG_SKIP_MQTT) == 0) {
if (bCallCb) {
- MQTT_ChannelPublish(ch,0);
+ MQTT_ChannelPublish(ch, 0);
}
}
// Simple event - it just says that there was a change
@@ -1287,7 +1287,7 @@ bool CHANNEL_IsPowerRelayChannel(int ch) {
int i;
for (i = 0; i < PLATFORM_GPIO_MAX; i++) {
if (g_cfg.pins.channels[i] == ch) {
- int role = g_cfg.pins.roles[i];
+ int role = g_cfg.pins.roles[i];
// NOTE: do not include Battery relay
if (role == IOR_Relay || role == IOR_Relay_n) {
return true;
@@ -1305,7 +1305,7 @@ bool CHANNEL_HasRoleThatShouldBePublished(int ch) {
if (role == IOR_Relay || role == IOR_Relay_n
|| role == IOR_LED || role == IOR_LED_n
|| role == IOR_ADC || role == IOR_BAT_ADC || role == IOR_BAT_Relay
- || role == IOR_CHT8305_DAT || role == IOR_SHT3X_DAT
+ || role == IOR_CHT8305_DAT || role == IOR_SHT3X_DAT || role == IOR_SGP_DAT
|| role == IOR_DigitalInput || role == IOR_DigitalInput_n
|| role == IOR_DoorSensorWithDeepSleep || role == IOR_DoorSensorWithDeepSleep_NoPup
|| role == IOR_DoorSensorWithDeepSleep_pd
@@ -1318,8 +1318,8 @@ bool CHANNEL_HasRoleThatShouldBePublished(int ch) {
if (IS_PIN_DHT_ROLE(role)) {
return true;
}
- // CHT8305 and SHT3X uses secondary channel for humidity
- if (role == IOR_CHT8305_DAT || role == IOR_SHT3X_DAT) {
+ // SGP, CHT8305 and SHT3X uses secondary channel for humidity
+ if (role == IOR_CHT8305_DAT || role == IOR_SHT3X_DAT || role == IOR_SGP_DAT) {
return true;
}
}
diff --git a/src/new_pins.h b/src/new_pins.h
index 32018a944..a30c70494 100644
--- a/src/new_pins.h
+++ b/src/new_pins.h
@@ -123,13 +123,13 @@ typedef enum ioRole_e {
//iodetail:"file":"new_pins.h",
//iodetail:"driver":""}
IOR_DigitalInput_NoPup_n,
-// energy sensor
- //iodetail:{"name":"BL0937_SEL",
- //iodetail:"title":"TODO",
- //iodetail:"descr":"SEL pin for BL0937 energy measuring devices. Set all BL0937 pins to autostart BL0937 driver. Don't forget to calibrate it later.",
- //iodetail:"enum":"IOR_BL0937_SEL",
- //iodetail:"file":"new_pins.h",
- //iodetail:"driver":""}
+ // energy sensor
+ //iodetail:{"name":"BL0937_SEL",
+ //iodetail:"title":"TODO",
+ //iodetail:"descr":"SEL pin for BL0937 energy measuring devices. Set all BL0937 pins to autostart BL0937 driver. Don't forget to calibrate it later.",
+ //iodetail:"enum":"IOR_BL0937_SEL",
+ //iodetail:"file":"new_pins.h",
+ //iodetail:"driver":""}
IOR_BL0937_SEL,
//iodetail:{"name":"BL0937_CF",
//iodetail:"title":"TODO",
@@ -467,6 +467,20 @@ typedef enum ioRole_e {
//iodetail:"file":"new_pins.h",
//iodetail:"driver":""}
IOR_DoorSensorWithDeepSleep_pd,
+ //iodetail:{"name":"SGP_CLK",
+ //iodetail:"title":"TODO",
+ //iodetail:"descr":"SGP Quality Sensor Clock line. will autostart related driver",
+ //iodetail:"enum":"IOR_SGP_CLK",
+ //iodetail:"file":"new_pins.h",
+ //iodetail:"driver":""}
+ IOR_SGP_CLK,
+ //iodetail:{"name":"SGP_DAT",
+ //iodetail:"title":"TODO",
+ //iodetail:"descr":"SGP Quality Sensor Data line. will autostart related driver",
+ //iodetail:"enum":"IOR_SGP_DAT",
+ //iodetail:"file":"new_pins.h",
+ //iodetail:"driver":""}
+ IOR_SGP_DAT,
//iodetail:{"name":"Total_Options",
//iodetail:"title":"TODO",
//iodetail:"descr":"Current total number of available IOR roles",
@@ -478,6 +492,7 @@ typedef enum ioRole_e {
#define IS_PIN_DHT_ROLE(role) (((role)>=IOR_DHT11) && ((role)<=IOR_DHT22))
#define IS_PIN_TEMP_HUM_SENSOR_ROLE(role) (((role)==IOR_SHT3X_DAT) || ((role)==IOR_CHT8305_DAT))
+#define IS_PIN_AIR_SENSOR_ROLE(role) (((role)==IOR_SGP_DAT))
typedef enum channelType_e {
//chandetail:{"name":"Default",
diff --git a/src/user_main.c b/src/user_main.c
index 67813c525..0f5b8128c 100644
--- a/src/user_main.c
+++ b/src/user_main.c
@@ -335,7 +335,7 @@ void Main_ScheduleHomeAssistantDiscovery(int seconds) {
}
void Main_ConnectToWiFiNow() {
- const char* wifi_ssid, *wifi_pass;
+ const char* wifi_ssid, * wifi_pass;
g_bOpenAccessPointMode = 0;
wifi_ssid = CFG_GetWiFiSSID();
@@ -698,7 +698,7 @@ void QuickTick(void* param)
#if (defined WINDOWS) || (defined PLATFORM_BEKEN)
SVM_RunThreads(t_diff);
#endif
- RepeatingEvents_RunUpdate(t_diff*0.001f);
+ RepeatingEvents_RunUpdate(t_diff * 0.001f);
#ifndef OBK_DISABLE_ALL_DRIVERS
DRV_RunQuickTick();
#endif
@@ -938,8 +938,8 @@ void Main_Init_BeforeDelay_Unsafe(bool bAutoRunScripts) {
DRV_StartDriver("BP1658CJ");
#endif
}
- if (PIN_FindPinIndexForRole(IOR_BL0937_CF, -1) != -1 && PIN_FindPinIndexForRole(IOR_BL0937_CF1, -1) != -1
- && (PIN_FindPinIndexForRole(IOR_BL0937_SEL, -1) != -1|| PIN_FindPinIndexForRole(IOR_BL0937_SEL_n, -1) != -1)) {
+ if (PIN_FindPinIndexForRole(IOR_BL0937_CF, -1) != -1 && PIN_FindPinIndexForRole(IOR_BL0937_CF1, -1) != -1
+ && (PIN_FindPinIndexForRole(IOR_BL0937_SEL, -1) != -1 || PIN_FindPinIndexForRole(IOR_BL0937_SEL_n, -1) != -1)) {
#ifndef OBK_DISABLE_ALL_DRIVERS
DRV_StartDriver("BL0937");
#endif
@@ -966,6 +966,11 @@ void Main_Init_BeforeDelay_Unsafe(bool bAutoRunScripts) {
if (PIN_FindPinIndexForRole(IOR_SHT3X_CLK, -1) != -1 && PIN_FindPinIndexForRole(IOR_SHT3X_DAT, -1) != -1) {
#ifndef OBK_DISABLE_ALL_DRIVERS
DRV_StartDriver("SHT3X");
+#endif
+ }
+ if (PIN_FindPinIndexForRole(IOR_SGP_CLK, -1) != -1 && PIN_FindPinIndexForRole(IOR_SGP_DAT, -1) != -1) {
+#ifndef OBK_DISABLE_ALL_DRIVERS
+ DRV_StartDriver("SGP");
#endif
}
if (PIN_FindPinIndexForRole(IOR_BAT_ADC, -1) != -1) {