diff --git a/openBeken_win32_mvsc2017.vcxproj b/openBeken_win32_mvsc2017.vcxproj
index 9d34c180b..f88751c5a 100644
--- a/openBeken_win32_mvsc2017.vcxproj
+++ b/openBeken_win32_mvsc2017.vcxproj
@@ -83,7 +83,7 @@
$(SolutionDir)$(Configuration)\
$(Configuration)\
- openBeken_win32
+ openBeken_win32
$(SolutionDir)$(Configuration)\
@@ -92,7 +92,7 @@
$(SolutionDir)$(Configuration)\
$(Configuration)\
- openBeken_win32
+ openBeken_win32
$(SolutionDir)$(Configuration)\
@@ -450,6 +450,7 @@
true
+
true
true
diff --git a/openBeken_win32_mvsc2017.vcxproj.filters b/openBeken_win32_mvsc2017.vcxproj.filters
index 58a093ea1..d51e36d3d 100644
--- a/openBeken_win32_mvsc2017.vcxproj.filters
+++ b/openBeken_win32_mvsc2017.vcxproj.filters
@@ -477,6 +477,9 @@
SelfTest
+
+ SelfTest
+
diff --git a/src/httpserver/http_fns.c b/src/httpserver/http_fns.c
index 35f441dd9..67a46cc43 100644
--- a/src/httpserver/http_fns.c
+++ b/src/httpserver/http_fns.c
@@ -1944,536 +1944,7 @@ int http_fn_ha_cfg(http_request_t* request) {
return 0;
}
-// https://tasmota.github.io/docs/Commands/#with-mqtt
-/*
-http:///cm?cmnd=Power%20TOGGLE
-http:///cm?cmnd=Power%20On
-http:///cm?cmnd=Power%20off
-http:///cm?user=admin&password=joker&cmnd=Power%20Toggle
-*/
-// https://www.elektroda.com/rtvforum/viewtopic.php?p=19330027#19330027
-// Web browser sends: GET /cm?cmnd=POWER1
-// System responds with state
-int http_tasmota_json_power(http_request_t* request) {
- int numRelays;
- int numPWMs;
- int i;
- int lastRelayState;
- bool bRelayIndexingStartsWithZero;
- int relayIndexingOffset;
- int temperature;
- int dimmer;
- bRelayIndexingStartsWithZero = CHANNEL_HasChannelPinWithRoleOrRole(0, IOR_Relay, IOR_Relay_n);
- if (bRelayIndexingStartsWithZero) {
- relayIndexingOffset = 0;
- }
- else {
- relayIndexingOffset = 1;
- }
-
- // try to return status
- numPWMs = PIN_CountPinsWithRoleOrRole(IOR_PWM, IOR_PWM_n);
- numRelays = 0;
-
- // LED driver (if has PWMs)
- if (LED_IsLEDRunning()) {
- dimmer = LED_GetDimmer();
- hprintf255(request, "\"Dimmer\":%i,", dimmer);
- hprintf255(request, "\"Fade\":\"OFF\",");
- hprintf255(request, "\"Speed\":1,");
- hprintf255(request, "\"LedTable\":\"ON\",");
- if (LED_IsLedDriverChipRunning() || numPWMs >= 3) {
- /*
- {
- POWER: "OFF",
- Dimmer: 100,
- Color: "255,0,157",
- HSBColor: "323,100,100",
- Channel: [
- 100,
- 0,
- 62
- ]
- }*/
- // Eg: Color: "255,0,157",
- byte rgbcw[5];
- int hsv[3];
- byte channels[5];
-
- LED_GetFinalRGBCW(rgbcw);
- LED_GetFinalHSV(hsv);
- LED_GetFinalChannels100(channels);
-
- // it looks like they include C and W in color
- if (LED_IsLedDriverChipRunning() || numPWMs == 5) {
- hprintf255(request, "\"Color\":\"%i,%i,%i,%i,%i\",",
- (int)rgbcw[0], (int)rgbcw[1], (int)rgbcw[2], (int)rgbcw[3], (int)rgbcw[4]);
- }
- else {
- hprintf255(request, "\"Color\":\"%i,%i,%i\",", (int)rgbcw[0], (int)rgbcw[1], (int)rgbcw[2]);
- }
- hprintf255(request, "\"HSBColor\":\"%i,%i,%i\",", hsv[0], hsv[1], hsv[2]);
- hprintf255(request, "\"Channel\":[%i,%i,%i],", (int)channels[0], (int)channels[1], (int)channels[2]);
-
- }
- if (LED_IsLedDriverChipRunning() || numPWMs == 5 || numPWMs == 2) {
- // 154 to 500 range
- temperature = LED_GetTemperature();
- // Temperature
- hprintf255(request, "\"CT\":%i,", temperature);
- }
- if (LED_GetEnableAll() == 0) {
- poststr(request, "\"POWER\":\"OFF\"");
- }
- else {
- poststr(request, "\"POWER\":\"ON\"");
- }
- }
- else {
- // relays driver
- for (i = 0; i < CHANNEL_MAX; i++) {
- if (h_isChannelRelay(i) || CHANNEL_GetType(i) == ChType_Toggle) {
- numRelays++;
- lastRelayState = CHANNEL_Get(i);
- }
- }
- if (numRelays == 1) {
- if (lastRelayState) {
- poststr(request, "\"POWER\":\"ON\"");
- }
- else {
- poststr(request, "\"POWER\":\"OFF\"");
- }
- }
- else {
- int c_posted = 0;
- for (i = 0; i < CHANNEL_MAX; i++) {
- if (h_isChannelRelay(i) || CHANNEL_GetType(i) == ChType_Toggle) {
- int indexStartingFrom1;
-
- if (bRelayIndexingStartsWithZero) {
- indexStartingFrom1 = i + 1;
- }
- else {
- indexStartingFrom1 = i;
- }
- lastRelayState = CHANNEL_Get(i);
- if (c_posted) {
- hprintf255(request, ",");
- }
- if (lastRelayState) {
- hprintf255(request, "\"POWER%i\":\"ON\"", indexStartingFrom1);
- }
- else {
- hprintf255(request, "\"POWER%i\":\"OFF\"", indexStartingFrom1);
- }
- c_posted++;
- }
- }
- }
-
- }
- return 0;
-}
-/*
-{"StatusSNS":{"Time":"2022-07-30T10:11:26","ENERGY":{"TotalStartTime":"2022-05-12T10:56:31","Total":0.003,"Yesterday":0.003,"Today":0.000,"Power": 0,"ApparentPower": 0,"ReactivePower": 0,"Factor":0.00,"Voltage":236,"Current":0.000}}}
-*/
-
-
-int http_tasmota_json_ENERGY(http_request_t* request) {
- float power, factor, voltage, current;
- float energy, energy_hour;
-
- factor = 0; // TODO
- voltage = DRV_GetReading(OBK_VOLTAGE);
- current = DRV_GetReading(OBK_CURRENT);
- power = DRV_GetReading(OBK_POWER);
- energy = DRV_GetReading(OBK_CONSUMPTION_TOTAL);
- energy_hour = DRV_GetReading(OBK_CONSUMPTION_LAST_HOUR);
-
- // following check will clear NaN values
- if (OBK_IS_NAN(energy)) {
- energy = 0;
- }
- if (OBK_IS_NAN(energy_hour)) {
- energy_hour = 0;
- }
- hprintf255(request, "{");
- hprintf255(request, "\"Power\": %f,", power);
- hprintf255(request, "\"ApparentPower\": 0,\"ReactivePower\": 0,\"Factor\":%f,", factor);
- hprintf255(request, "\"Voltage\":%f,", voltage);
- hprintf255(request, "\"Current\":%f,", current);
- hprintf255(request, "\"ConsumptionTotal\":%f,", energy);
- hprintf255(request, "\"ConsumptionLastHour\":%f", energy_hour);
- // close ENERGY block
- hprintf255(request, "}");
- return 0;
-}
-
-// Topic: tele/tasmota_48E7F3/SENSOR at 3:06 AM:
-// Sample:
-/*
-{
- "Time": "2022-12-30T03:06:36",
- "ENERGY": {
- "TotalStartTime": "2022-05-12T10:56:31",
- "Total": 0.007,
- "Yesterday": 0,
- "Today": 0,
- "Period": 0,
- "Power": 0,
- "ApparentPower": 0,
- "ReactivePower": 0,
- "Factor": 0,
- "Voltage": 241,
- "Current": 0
- }
-}
-*/
-int http_tasmota_json_status_SNS(http_request_t* request) {
- char buff[20];
-
- hprintf255(request, "\"StatusSNS\":{");
-
- time_t localTime = (time_t)NTP_GetCurrentTime();
- strftime(buff, sizeof(buff), "%Y-%m-%dT%H:%M:%S", localtime(&localTime));
- hprintf255(request, "\"Time\":\"%s\"", buff);
-
-#ifndef OBK_DISABLE_ALL_DRIVERS
- if (DRV_IsMeasuringPower()) {
-
- // begin ENERGY block
- hprintf255(request, ",");
- hprintf255(request, "\"ENERGY\":");
- http_tasmota_json_ENERGY(request);
- }
-#endif
-
- hprintf255(request, "}");
-
- return 0;
-}
-
-#ifdef PLATFORM_XR809
-//XR809 does not support drivers but its build script compiles many drivers including ntp.
-
-#else
-#ifndef ENABLE_BASIC_DRIVERS
-unsigned int NTP_GetCurrentTime() {
- return 0;
-}
-unsigned int NTP_GetCurrentTimeWithoutOffset() {
- return 0;
-}
-#endif
-#endif
-
-// Topic: tele/tasmota_48E7F3/STATE
-// Sample:
-/*
-{
- "Time": "2022-12-30T03:06:36",
- "Uptime": "0T06:16:14",
- "UptimeSec": 22574,
- "Heap": 26,
- "SleepMode": "Dynamic",
- "Sleep": 50,
- "LoadAvg": 19,
- "MqttCount": 1,
- "POWER": "ON",
- "Wifi": {
- "AP": 1,
- "SSId": "ASUS_25G_WIFI",
- "BSSId": "32:21:BA:10:F6:6D",
- "Channel": 3,
- "Mode": "11n",
- "RSSI": 62,
- "Signal": -69,
- "LinkCount": 1,
- "Downtime": "0T00:00:04"
- }
-}
-*/
-int http_tasmota_json_status_STS(http_request_t* request) {
- char buff[20];
- time_t localTime = (time_t)NTP_GetCurrentTime();
-
- hprintf255(request, "{");
- strftime(buff, sizeof(buff), "%Y-%m-%dT%H:%M:%S", localtime(&localTime));
- hprintf255(request, "\"Time\":\"%s\",", buff);
- hprintf255(request, "\"Uptime\":\"30T02:59:30\",");
- hprintf255(request, "\"UptimeSec\":%i,", Time_getUpTimeSeconds());
- hprintf255(request, "\"Heap\":25,");
- hprintf255(request, "\"SleepMode\":\"Dynamic\",");
- hprintf255(request, "\"Sleep\":10,");
- hprintf255(request, "\"LoadAvg\":99,");
- hprintf255(request, "\"MqttCount\":23,");
-
- http_tasmota_json_power(request);
- hprintf255(request, ",");
- hprintf255(request, "\"Wifi\":{"); // open WiFi
- hprintf255(request, "\"AP\":1,");
- hprintf255(request, "\"SSId\":\"%s\",", CFG_GetWiFiSSID());
- hprintf255(request, "\"BSSId\":\"30:B5:C2:5D:70:72\",");
- hprintf255(request, "\"Channel\":11,");
- hprintf255(request, "\"Mode\":\"11n\",");
- hprintf255(request, "\"RSSI\":78,");
- hprintf255(request, "\"Signal\":%i,", HAL_GetWifiStrength());
- hprintf255(request, "\"LinkCount\":21,");
- hprintf255(request, "\"Downtime\":\"0T06:13:34\"");
- hprintf255(request, "}"); // close WiFi
- hprintf255(request, "}");
- return 0;
-}
-/*
-{"Status":{"Module":0,"DeviceName":"Tasmota","FriendlyName":["Tasmota"],"Topic":"tasmota_48E7F3","ButtonTopic":"0","Power":1,"PowerOnState":3,"LedState":1,"LedMask":"FFFF","SaveData":1,"SaveState":1,"SwitchTopic":"0","SwitchMode":[0,0,0,0,0,0,0,0],"ButtonRetain":0,"SwitchRetain":0,"SensorRetain":0,"PowerRetain":0,"InfoRetain":0,"StateRetain":0}}
-*/
-int http_tasmota_json_status_generic(http_request_t* request) {
- const char* deviceName;
- const char* friendlyName;
- const char* clientId;
- int powerCode;
- int relayCount, pwmCount, dInputCount, i;
- bool bRelayIndexingStartsWithZero;
- char buff[20];
-
- deviceName = CFG_GetShortDeviceName();
- friendlyName = CFG_GetDeviceName();
- clientId = CFG_GetMQTTClientId();
-
- //deviceName = "Tasmota";
- //friendlyName - "Tasmota";
-
-#if 0
- const char* dbg = "{\"Status\":{\"Module\":0,\"DeviceName\":\"Tasmota\",\"FriendlyName\":[\"Tasmota\"],\"Topic\":\"tasmota_D79E2C\",\"ButtonTopic\":\"0\",\"Power\":1,\"PowerOnState\":3,\"LedState\":1,\"LedMask\":\"FFFF\",\"SaveData\":1,\"SaveState\":1,\"SwitchTopic\":\"0\",\"SwitchMode\":[0,0,0,0,0,0,0,0],\"ButtonRetain\":0,\"SwitchRetain\":0,\"SensorRetain\":0,\"PowerRetain\":0,\"InfoRetain\":0,\"StateRetain\":0},\"StatusPRM\":{\"Baudrate\":115200,\"SerialConfig\":\"8N1\",\"GroupTopic\":\"tasmotas\",\"OtaUrl\":\"http://ota.tasmota.com/tasmota/release/tasmota.bin.gz\",\"RestartReason\":\"Hardware Watchdog\",\"Uptime\":\"30T03:43:17\",\"StartupUTC\":\"2022-10-10T16:09:41\",\"Sleep\":50,\"CfgHolder\":4617,\"BootCount\":22,\"BCResetTime\":\"2022-01-27T16:10:56\",\"SaveCount\":1235,\"SaveAddress\":\"F9000\"},\"StatusFWR\":{\"Version\":\"10.1.0(tasmota)\",\"BuildDateTime\":\"2021-12-08T14:47:33\",\"Boot\":7,\"Core\":\"2_7_4_9\",\"SDK\":\"2.2.2-dev(38a443e)\",\"CpuFrequency\":80,\"Hardware\":\"ESP8266EX\",\"CR\":\"465/699\"},\"StatusLOG\":{\"SerialLog\":2,\"WebLog\":2,\"MqttLog\":0,\"SysLog\":0,\"LogHost\":\"\",\"LogPort\":514,\"SSId\":[\"DLINK_FastNet\",\"\"],\"TelePeriod\":300,\"Resolution\":\"558180C0\",\"SetOption\":[\"000A8009\",\"2805C80001000600003C5A0A000000000000\",\"00000280\",\"00006008\",\"00004000\"]},\"StatusMEM\":{\"ProgramSize\":616,\"Free\":384,\"Heap\":25,\"ProgramFlashSize\":1024,\"FlashSize\":2048,\"FlashChipId\":\"1540A1\",\"FlashFrequency\":40,\"FlashMode\":3,\"Features\":[\"00000809\",\"8FDAC787\",\"04368001\",\"000000CF\",\"010013C0\",\"C000F981\",\"00004004\",\"00001000\",\"00000020\"],\"Drivers\":\"1,2,3,4,5,6,7,8,9,10,12,16,18,19,20,21,22,24,26,27,29,30,35,37,45\",\"Sensors\":\"1,2,3,4,5,6\"},\"StatusNET\":{\"Hostname\":\"tasmota-D79E2C-7724\",\"IPAddress\":\"192.168.0.104\",\"Gateway\":\"192.168.0.1\",\"Subnetmask\":\"255.255.255.0\",\"DNSServer1\":\"192.168.0.1\",\"DNSServer2\":\"0.0.0.0\",\"Mac\":\"10:52:1C:D7:9E:2C\",\"Webserver\":2,\"HTTP_API\":1,\"WifiConfig\":4,\"WifiPower\":17.0},\"StatusMQT\":{\"MqttHost\":\"192.168.0.113\",\"MqttPort\":1883,\"MqttClientMask\":\"core-mosquitto\",\"MqttClient\":\"core-mosquitto\",\"MqttUser\":\"homeassistant\",\"MqttCount\":23,\"MAX_PACKET_SIZE\":1200,\"KEEPALIVE\":30,\"SOCKET_TIMEOUT\":4},\"StatusTIM\":{\"UTC\":\"2022-11-09T19:52:58\",\"Local\":\"2022-11-09T20:52:58\",\"StartDST\":\"2022-03-27T02:00:00\",\"EndDST\":\"2022-10-30T03:00:00\",\"Timezone\":\"+01:00\",\"Sunrise\":\"07:50\",\"Sunset\":\"17:17\"},\"StatusSNS\":{\"Time\":\"2022-11-09T20:52:58\"},\"StatusSTS\":{\"Time\":\"2022-11-09T20:52:58\",\"Uptime\":\"30T03:43:17\",\"UptimeSec\":2605397,\"Heap\":25,\"SleepMode\":\"Dynamic\",\"Sleep\":10,\"LoadAvg\":99,\"MqttCount\":23,\"POWER\":\"ON\",\"Dimmer\":99,\"Fade\":\"OFF\",\"Speed\":1,\"LedTable\":\"ON\",\"Wifi\":{\"AP\":1,\"SSId\":\"DLINK_FastNet\",\"BSSId\":\"30:B5:C2:5D:70:72\",\"Channel\":11,\"Mode\":\"11n\",\"RSSI\":80,\"Signal\":-60,\"LinkCount\":21,\"Downtime\":\"0T06:13:34\"}}}";
- poststr(request, dbg);
- return;
-
-#endif
-
- bRelayIndexingStartsWithZero = CHANNEL_HasChannelPinWithRoleOrRole(0, IOR_Relay, IOR_Relay_n);
-
- get_Relay_PWM_Count(&relayCount, &pwmCount, &dInputCount);
-
- if (LED_IsLEDRunning()) {
- powerCode = LED_GetEnableAll();
- }
- else {
- powerCode = 0;
- for (i = 0; i < CHANNEL_MAX; i++) {
- bool bRelay;
- int useIdx;
- int iValue;
- if (bRelayIndexingStartsWithZero) {
- useIdx = i;
- }
- else {
- useIdx = i + 1;
- }
- bRelay = CHANNEL_HasChannelPinWithRoleOrRole(useIdx, IOR_Relay, IOR_Relay_n);
- if (bRelay) {
- iValue = CHANNEL_Get(useIdx);
- if (iValue)
- BIT_SET(powerCode, i);
- else
- BIT_CLEAR(powerCode, i);
- }
- }
- }
-
- hprintf255(request, "{");
- // Status section
- hprintf255(request, "\"Status\":{\"Module\":0,\"DeviceName\":\"%s\"", deviceName);
- hprintf255(request, ",\"FriendlyName\":[");
- if (relayCount == 0) {
- hprintf255(request, "\"%s\"", deviceName);
- }
- else {
- int c_printed = 0;
- for (i = 0; i < CHANNEL_MAX; i++) {
- bool bRelay;
- bRelay = CHANNEL_HasChannelPinWithRoleOrRole(i, IOR_Relay, IOR_Relay_n);
- if (bRelay) {
- int useIdx;
- if (bRelayIndexingStartsWithZero) {
- useIdx = i + 1;
- }
- else {
- useIdx = i;
- }
- if (c_printed) {
- hprintf255(request, ",");
- }
- hprintf255(request, "\"%s_%i\"", deviceName, useIdx);
- c_printed++;
- }
- }
- }
- hprintf255(request, "]");
- hprintf255(request, ",\"Topic\":\"%s\",\"ButtonTopic\":\"0\"", clientId);
- hprintf255(request, ",\"Power\":%i,\"PowerOnState\":3,\"LedState\":1", powerCode);
- hprintf255(request, ",\"LedMask\":\"FFFF\",\"SaveData\":1,\"SaveState\":1");
- hprintf255(request, ",\"SwitchTopic\":\"0\",\"SwitchMode\":[0,0,0,0,0,0,0,0]");
- hprintf255(request, ",\"ButtonRetain\":0,\"SwitchRetain\":0,\"SensorRetain\":0");
- hprintf255(request, ",\"PowerRetain\":0,\"InfoRetain\":0,\"StateRetain\":0");
- hprintf255(request, "}");
-
- hprintf255(request, ",");
-
-
- hprintf255(request, "\"StatusPRM\":{");
- hprintf255(request, "\"Baudrate\":115200,");
- hprintf255(request, "\"SerialConfig\":\"8N1\",");
- hprintf255(request, "\"GroupTopic\":\"tasmotas\",");
- hprintf255(request, "\"OtaUrl\":\"http://ota.tasmota.com/tasmota/release/tasmota.bin.gz\",");
- hprintf255(request, "\"RestartReason\":\"HardwareWatchdog\",");
- hprintf255(request, "\"Uptime\":\"30T02:59:30\",");
- hprintf255(request, "\"StartupUTC\":\"2022-10-10T16:09:41\",");
- hprintf255(request, "\"Sleep\":50,");
- hprintf255(request, "\"CfgHolder\":4617,");
- hprintf255(request, "\"BootCount\":22,");
- hprintf255(request, "\"BCResetTime\":\"2022-01-27T16:10:56\",");
- hprintf255(request, "\"SaveCount\":1235,");
- hprintf255(request, "\"SaveAddress\":\"F9000\"");
- hprintf255(request, "}");
-
- hprintf255(request, ",");
-
- hprintf255(request, "\"StatusFWR\":{");
- hprintf255(request, "\"Version\":\"%s\",", DEVICENAME_PREFIX_FULL"_"USER_SW_VER);
- hprintf255(request, "\"BuildDateTime\":\"%s\",", __DATE__ " " __TIME__);
- hprintf255(request, "\"Boot\":7,");
- hprintf255(request, "\"Core\":\"%s\",", "0.0");
- hprintf255(request, "\"SDK\":\"\",", "obk");
- hprintf255(request, "\"CpuFrequency\":80,");
- hprintf255(request, "\"Hardware\":\"%s\",", PLATFORM_MCU_NAME);
- hprintf255(request, "\"CR\":\"465/699\"");
- hprintf255(request, "}");
-
- hprintf255(request, ",");
-
-
-
- hprintf255(request, "\"StatusLOG\":{");
- hprintf255(request, "\"SerialLog\":2,");
- hprintf255(request, "\"WebLog\":2,");
- hprintf255(request, "\"MqttLog\":0,");
- hprintf255(request, "\"SysLog\":0,");
- hprintf255(request, "\"LogHost\":\"\",");
- hprintf255(request, "\"LogPort\":514,");
- hprintf255(request, "\"SSId\":[");
- hprintf255(request, "\"%s\",", CFG_GetWiFiSSID());
- hprintf255(request, "\"\"");
- hprintf255(request, "],");
- hprintf255(request, "\"TelePeriod\":300,");
- hprintf255(request, "\"Resolution\":\"558180C0\",");
- hprintf255(request, "\"SetOption\":[");
- hprintf255(request, "\"000A8009\",");
- hprintf255(request, "\"2805C80001000600003C5A0A000000000000\",");
- hprintf255(request, "\"00000280\",");
- hprintf255(request, "\"00006008\",");
- hprintf255(request, "\"00004000\"");
- hprintf255(request, "]");
- hprintf255(request, "}");
-
- hprintf255(request, ",");
-
-
-
- hprintf255(request, "\"StatusMEM\":{");
- hprintf255(request, "\"ProgramSize\":616,");
- hprintf255(request, "\"Free\":384,");
- hprintf255(request, "\"Heap\":25,");
- hprintf255(request, "\"ProgramFlashSize\":1024,");
- hprintf255(request, "\"FlashSize\":2048,");
- hprintf255(request, "\"FlashChipId\":\"1540A1\",");
- hprintf255(request, "\"FlashFrequency\":40,");
- hprintf255(request, "\"FlashMode\":3,");
- hprintf255(request, "\"Features\":[");
- hprintf255(request, "\"00000809\",");
- hprintf255(request, "\"8FDAC787\",");
- hprintf255(request, "\"04368001\",");
- hprintf255(request, "\"000000CF\",");
- hprintf255(request, "\"010013C0\",");
- hprintf255(request, "\"C000F981\",");
- hprintf255(request, "\"00004004\",");
- hprintf255(request, "\"00001000\",");
- hprintf255(request, "\"00000020\"");
- hprintf255(request, "],");
- hprintf255(request, "\"Drivers\":\"1,2,3,4,5,6,7,8,9,10,12,16,18,19,20,21,22,24,26,27,29,30,35,37,45\",");
- hprintf255(request, "\"Sensors\":\"1,2,3,4,5,6\"");
- hprintf255(request, "}");
-
- hprintf255(request, ",");
-
-
- hprintf255(request, "\"StatusNET\":{");
- hprintf255(request, "\"Hostname\":\"%s\",", CFG_GetShortDeviceName());
- hprintf255(request, "\"IPAddress\":\"%s\",", HAL_GetMyIPString());
- hprintf255(request, "\"Gateway\":\"192.168.0.1\",");
- hprintf255(request, "\"Subnetmask\":\"255.255.255.0\",");
- hprintf255(request, "\"DNSServer1\":\"192.168.0.1\",");
- hprintf255(request, "\"DNSServer2\":\"0.0.0.0\",");
- hprintf255(request, "\"Mac\":\"10:52:1C:D7:9E:2C\",");
- hprintf255(request, "\"Webserver\":2,");
- hprintf255(request, "\"HTTP_API\":1,");
- hprintf255(request, "\"WifiConfig\":4,");
- hprintf255(request, "\"WifiPower\":17.0");
- hprintf255(request, "}");
- hprintf255(request, ",");
-
-
-
-
- hprintf255(request, "\"StatusMQT\":{");
- hprintf255(request, "\"MqttHost\":\"%s\",", CFG_GetMQTTHost());
- hprintf255(request, "\"MqttPort\":%i,", CFG_GetMQTTPort());
- hprintf255(request, "\"MqttClientMask\":\"core-mosquitto\",");
- hprintf255(request, "\"MqttClient\":\"%s\",", CFG_GetMQTTClientId());
- hprintf255(request, "\"MqttUser\":\"%s\",", CFG_GetMQTTUserName());
- hprintf255(request, "\"MqttCount\":23,");
- hprintf255(request, "\"MAX_PACKET_SIZE\":1200,");
- hprintf255(request, "\"KEEPALIVE\":30,");
- hprintf255(request, "\"SOCKET_TIMEOUT\":4");
- hprintf255(request, "}");
-
- hprintf255(request, ",");
- time_t localTime = (time_t)NTP_GetCurrentTime();
- {
- time_t localUTC = (time_t)NTP_GetCurrentTimeWithoutOffset();
-
- hprintf255(request, "\"StatusTIM\":{");
- strftime(buff, sizeof(buff), "%Y-%m-%dT%H:%M:%S", localtime(&localUTC));
- hprintf255(request, "\"UTC\":\"%s\",", buff);
- strftime(buff, sizeof(buff), "%Y-%m-%dT%H:%M:%S", localtime(&localTime));
- hprintf255(request, "\"Local\":\"%s\",", buff);
- hprintf255(request, "\"StartDST\":\"2022-03-27T02:00:00\",");
- hprintf255(request, "\"EndDST\":\"2022-10-30T03:00:00\",");
- hprintf255(request, "\"Timezone\":\"+01:00\",");
- hprintf255(request, "\"Sunrise\":\"07:50\",");
- hprintf255(request, "\"Sunset\":\"17:17\"");
- hprintf255(request, "}");
- }
-
- hprintf255(request, ",");
-
-
- http_tasmota_json_status_SNS(request);
-
- hprintf255(request, ",");
-
- hprintf255(request, "\"StatusSTS\":");
-
- http_tasmota_json_status_STS(request);
-
- // end
- hprintf255(request, "}");
-
-
-
- return 0;
-}
int http_fn_cm(http_request_t* request) {
char tmpA[128];
char *long_str_alloced = 0;
@@ -2489,28 +1960,14 @@ int http_fn_cm(http_request_t* request) {
if (long_str_alloced) {
http_getArg(request->url, "cmnd", long_str_alloced, commandLen);
CMD_ExecuteCommand(long_str_alloced, COMMAND_FLAG_SOURCE_HTTP);
+ JSON_ProcessCommandReply(long_str_alloced, request, hprintf255, COMMAND_FLAG_SOURCE_HTTP);
free(long_str_alloced);
}
}
else {
CMD_ExecuteCommand(tmpA, COMMAND_FLAG_SOURCE_HTTP);
+ JSON_ProcessCommandReply(tmpA, request, hprintf255, COMMAND_FLAG_SOURCE_HTTP);
}
-
- if (!wal_strnicmp(tmpA, "POWER", 5)) {
-
- poststr(request, "{");
- http_tasmota_json_power(request);
- poststr(request, "}");
- }
- else if (!wal_strnicmp(tmpA, "STATUS 8", 8) || !wal_strnicmp(tmpA, "STATUS 10", 10)) {
- hprintf255(request, "{");
- http_tasmota_json_status_SNS(request);
- hprintf255(request, "}");
- }
- else {
- http_tasmota_json_status_generic(request);
- }
-
}
poststr(request, NULL);
diff --git a/src/httpserver/json_interface.c b/src/httpserver/json_interface.c
new file mode 100644
index 000000000..a03d3dcc2
--- /dev/null
+++ b/src/httpserver/json_interface.c
@@ -0,0 +1,586 @@
+#include "../new_common.h"
+#include "http_fns.h"
+#include "../new_pins.h"
+#include "../new_cfg.h"
+#include "../ota/ota.h"
+// Commands register, execution API and cmd tokenizer
+#include "../cmnds/cmd_public.h"
+#include "../driver/drv_tuyaMCU.h"
+#include "../driver/drv_public.h"
+#include "../hal/hal_wifi.h"
+#include "../hal/hal_pins.h"
+#include "../hal/hal_flashConfig.h"
+#include "../logging/logging.h"
+#include "../devicegroups/deviceGroups_public.h"
+#include "../mqtt/new_mqtt.h"
+#include "hass.h"
+#include "../cJSON/cJSON.h"
+#include
+#include "../driver/drv_ntp.h"
+#include "../driver/drv_local.h"
+
+
+
+// https://tasmota.github.io/docs/Commands/#with-mqtt
+/*
+http:///cm?cmnd=Power%20TOGGLE
+http:///cm?cmnd=Power%20On
+http:///cm?cmnd=Power%20off
+http:///cm?user=admin&password=joker&cmnd=Power%20Toggle
+*/
+// https://www.elektroda.com/rtvforum/viewtopic.php?p=19330027#19330027
+// Web browser sends: GET /cm?cmnd=POWER1
+// System responds with state
+static int http_tasmota_json_power(void* request, jsonCb_t printer) {
+ int numRelays;
+ int numPWMs;
+ int i;
+ int lastRelayState;
+ bool bRelayIndexingStartsWithZero;
+ int relayIndexingOffset;
+ int temperature;
+ int dimmer;
+
+ bRelayIndexingStartsWithZero = CHANNEL_HasChannelPinWithRoleOrRole(0, IOR_Relay, IOR_Relay_n);
+ if (bRelayIndexingStartsWithZero) {
+ relayIndexingOffset = 0;
+ }
+ else {
+ relayIndexingOffset = 1;
+ }
+
+ // try to return status
+ numPWMs = PIN_CountPinsWithRoleOrRole(IOR_PWM, IOR_PWM_n);
+ numRelays = 0;
+
+ // LED driver (if has PWMs)
+ if (LED_IsLEDRunning()) {
+ dimmer = LED_GetDimmer();
+ printer(request, "\"Dimmer\":%i,", dimmer);
+ printer(request, "\"Fade\":\"OFF\",");
+ printer(request, "\"Speed\":1,");
+ printer(request, "\"LedTable\":\"ON\",");
+ if (LED_IsLedDriverChipRunning() || numPWMs >= 3) {
+ /*
+ {
+ POWER: "OFF",
+ Dimmer: 100,
+ Color: "255,0,157",
+ HSBColor: "323,100,100",
+ Channel: [
+ 100,
+ 0,
+ 62
+ ]
+ }*/
+ // Eg: Color: "255,0,157",
+ byte rgbcw[5];
+ int hsv[3];
+ byte channels[5];
+
+ LED_GetFinalRGBCW(rgbcw);
+ LED_GetFinalHSV(hsv);
+ LED_GetFinalChannels100(channels);
+
+ // it looks like they include C and W in color
+ if (LED_IsLedDriverChipRunning() || numPWMs == 5) {
+ printer(request, "\"Color\":\"%i,%i,%i,%i,%i\",",
+ (int)rgbcw[0], (int)rgbcw[1], (int)rgbcw[2], (int)rgbcw[3], (int)rgbcw[4]);
+ }
+ else {
+ printer(request, "\"Color\":\"%i,%i,%i\",", (int)rgbcw[0], (int)rgbcw[1], (int)rgbcw[2]);
+ }
+ printer(request, "\"HSBColor\":\"%i,%i,%i\",", hsv[0], hsv[1], hsv[2]);
+ printer(request, "\"Channel\":[%i,%i,%i],", (int)channels[0], (int)channels[1], (int)channels[2]);
+
+ }
+ if (LED_IsLedDriverChipRunning() || numPWMs == 5 || numPWMs == 2) {
+ // 154 to 500 range
+ temperature = LED_GetTemperature();
+ // Temperature
+ printer(request, "\"CT\":%i,", temperature);
+ }
+ if (LED_GetEnableAll() == 0) {
+ printer(request, "\"POWER\":\"OFF\"");
+ }
+ else {
+ printer(request, "\"POWER\":\"ON\"");
+ }
+ }
+ else {
+ // relays driver
+ for (i = 0; i < CHANNEL_MAX; i++) {
+ if (h_isChannelRelay(i) || CHANNEL_GetType(i) == ChType_Toggle) {
+ numRelays++;
+ lastRelayState = CHANNEL_Get(i);
+ }
+ }
+ if (numRelays == 1) {
+ if (lastRelayState) {
+ printer(request, "\"POWER\":\"ON\"");
+ }
+ else {
+ printer(request, "\"POWER\":\"OFF\"");
+ }
+ }
+ else {
+ int c_posted = 0;
+ for (i = 0; i < CHANNEL_MAX; i++) {
+ if (h_isChannelRelay(i) || CHANNEL_GetType(i) == ChType_Toggle) {
+ int indexStartingFrom1;
+
+ if (bRelayIndexingStartsWithZero) {
+ indexStartingFrom1 = i + 1;
+ }
+ else {
+ indexStartingFrom1 = i;
+ }
+ lastRelayState = CHANNEL_Get(i);
+ if (c_posted) {
+ printer(request, ",");
+ }
+ if (lastRelayState) {
+ printer(request, "\"POWER%i\":\"ON\"", indexStartingFrom1);
+ }
+ else {
+ printer(request, "\"POWER%i\":\"OFF\"", indexStartingFrom1);
+ }
+ c_posted++;
+ }
+ }
+ }
+
+ }
+ return 0;
+}
+/*
+{"StatusSNS":{"Time":"2022-07-30T10:11:26","ENERGY":{"TotalStartTime":"2022-05-12T10:56:31","Total":0.003,"Yesterday":0.003,"Today":0.000,"Power": 0,"ApparentPower": 0,"ReactivePower": 0,"Factor":0.00,"Voltage":236,"Current":0.000}}}
+*/
+
+
+static int http_tasmota_json_ENERGY(void* request, jsonCb_t printer) {
+ float power, factor, voltage, current;
+ float energy, energy_hour;
+
+ factor = 0; // TODO
+ voltage = DRV_GetReading(OBK_VOLTAGE);
+ current = DRV_GetReading(OBK_CURRENT);
+ power = DRV_GetReading(OBK_POWER);
+ energy = DRV_GetReading(OBK_CONSUMPTION_TOTAL);
+ energy_hour = DRV_GetReading(OBK_CONSUMPTION_LAST_HOUR);
+
+ // following check will clear NaN values
+ if (OBK_IS_NAN(energy)) {
+ energy = 0;
+ }
+ if (OBK_IS_NAN(energy_hour)) {
+ energy_hour = 0;
+ }
+ printer(request, "{");
+ printer(request, "\"Power\": %f,", power);
+ printer(request, "\"ApparentPower\": 0,\"ReactivePower\": 0,\"Factor\":%f,", factor);
+ printer(request, "\"Voltage\":%f,", voltage);
+ printer(request, "\"Current\":%f,", current);
+ printer(request, "\"ConsumptionTotal\":%f,", energy);
+ printer(request, "\"ConsumptionLastHour\":%f", energy_hour);
+ // close ENERGY block
+ printer(request, "}");
+ return 0;
+}
+
+// Topic: tele/tasmota_48E7F3/SENSOR at 3:06 AM:
+// Sample:
+/*
+{
+ "Time": "2022-12-30T03:06:36",
+ "ENERGY": {
+ "TotalStartTime": "2022-05-12T10:56:31",
+ "Total": 0.007,
+ "Yesterday": 0,
+ "Today": 0,
+ "Period": 0,
+ "Power": 0,
+ "ApparentPower": 0,
+ "ReactivePower": 0,
+ "Factor": 0,
+ "Voltage": 241,
+ "Current": 0
+ }
+}
+*/
+static int http_tasmota_json_status_SNS(void* request, jsonCb_t printer) {
+ char buff[20];
+
+ printer(request, "\"StatusSNS\":{");
+
+ time_t localTime = (time_t)NTP_GetCurrentTime();
+ strftime(buff, sizeof(buff), "%Y-%m-%dT%H:%M:%S", localtime(&localTime));
+ printer(request, "\"Time\":\"%s\"", buff);
+
+#ifndef OBK_DISABLE_ALL_DRIVERS
+ if (DRV_IsMeasuringPower()) {
+
+ // begin ENERGY block
+ printer(request, ",");
+ printer(request, "\"ENERGY\":");
+ http_tasmota_json_ENERGY(request, printer);
+ }
+#endif
+
+ printer(request, "}");
+
+ return 0;
+}
+
+#ifdef PLATFORM_XR809
+//XR809 does not support drivers but its build script compiles many drivers including ntp.
+
+#else
+#ifndef ENABLE_BASIC_DRIVERS
+unsigned int NTP_GetCurrentTime() {
+ return 0;
+}
+unsigned int NTP_GetCurrentTimeWithoutOffset() {
+ return 0;
+}
+#endif
+#endif
+
+// Topic: tele/tasmota_48E7F3/STATE
+// Sample:
+/*
+{
+ "Time": "2022-12-30T03:06:36",
+ "Uptime": "0T06:16:14",
+ "UptimeSec": 22574,
+ "Heap": 26,
+ "SleepMode": "Dynamic",
+ "Sleep": 50,
+ "LoadAvg": 19,
+ "MqttCount": 1,
+ "POWER": "ON",
+ "Wifi": {
+ "AP": 1,
+ "SSId": "ASUS_25G_WIFI",
+ "BSSId": "32:21:BA:10:F6:6D",
+ "Channel": 3,
+ "Mode": "11n",
+ "RSSI": 62,
+ "Signal": -69,
+ "LinkCount": 1,
+ "Downtime": "0T00:00:04"
+ }
+}
+*/
+static int http_tasmota_json_status_STS(void* request, jsonCb_t printer) {
+ char buff[20];
+ time_t localTime = (time_t)NTP_GetCurrentTime();
+
+ printer(request, "{");
+ strftime(buff, sizeof(buff), "%Y-%m-%dT%H:%M:%S", localtime(&localTime));
+ printer(request, "\"Time\":\"%s\",", buff);
+ printer(request, "\"Uptime\":\"30T02:59:30\",");
+ printer(request, "\"UptimeSec\":%i,", Time_getUpTimeSeconds());
+ printer(request, "\"Heap\":25,");
+ printer(request, "\"SleepMode\":\"Dynamic\",");
+ printer(request, "\"Sleep\":10,");
+ printer(request, "\"LoadAvg\":99,");
+ printer(request, "\"MqttCount\":23,");
+
+ http_tasmota_json_power(request, printer);
+ printer(request, ",");
+ printer(request, "\"Wifi\":{"); // open WiFi
+ printer(request, "\"AP\":1,");
+ printer(request, "\"SSId\":\"%s\",", CFG_GetWiFiSSID());
+ printer(request, "\"BSSId\":\"30:B5:C2:5D:70:72\",");
+ printer(request, "\"Channel\":11,");
+ printer(request, "\"Mode\":\"11n\",");
+ printer(request, "\"RSSI\":78,");
+ printer(request, "\"Signal\":%i,", HAL_GetWifiStrength());
+ printer(request, "\"LinkCount\":21,");
+ printer(request, "\"Downtime\":\"0T06:13:34\"");
+ printer(request, "}"); // close WiFi
+ printer(request, "}");
+ return 0;
+}
+/*
+{"Status":{"Module":0,"DeviceName":"Tasmota","FriendlyName":["Tasmota"],"Topic":"tasmota_48E7F3","ButtonTopic":"0","Power":1,"PowerOnState":3,"LedState":1,"LedMask":"FFFF","SaveData":1,"SaveState":1,"SwitchTopic":"0","SwitchMode":[0,0,0,0,0,0,0,0],"ButtonRetain":0,"SwitchRetain":0,"SensorRetain":0,"PowerRetain":0,"InfoRetain":0,"StateRetain":0}}
+*/
+static int http_tasmota_json_status_generic(void* request, jsonCb_t printer) {
+ const char* deviceName;
+ const char* friendlyName;
+ const char* clientId;
+ int powerCode;
+ int relayCount, pwmCount, dInputCount, i;
+ bool bRelayIndexingStartsWithZero;
+ char buff[20];
+
+ deviceName = CFG_GetShortDeviceName();
+ friendlyName = CFG_GetDeviceName();
+ clientId = CFG_GetMQTTClientId();
+
+ //deviceName = "Tasmota";
+ //friendlyName - "Tasmota";
+
+#if 0
+ const char* dbg = "{\"Status\":{\"Module\":0,\"DeviceName\":\"Tasmota\",\"FriendlyName\":[\"Tasmota\"],\"Topic\":\"tasmota_D79E2C\",\"ButtonTopic\":\"0\",\"Power\":1,\"PowerOnState\":3,\"LedState\":1,\"LedMask\":\"FFFF\",\"SaveData\":1,\"SaveState\":1,\"SwitchTopic\":\"0\",\"SwitchMode\":[0,0,0,0,0,0,0,0],\"ButtonRetain\":0,\"SwitchRetain\":0,\"SensorRetain\":0,\"PowerRetain\":0,\"InfoRetain\":0,\"StateRetain\":0},\"StatusPRM\":{\"Baudrate\":115200,\"SerialConfig\":\"8N1\",\"GroupTopic\":\"tasmotas\",\"OtaUrl\":\"http://ota.tasmota.com/tasmota/release/tasmota.bin.gz\",\"RestartReason\":\"Hardware Watchdog\",\"Uptime\":\"30T03:43:17\",\"StartupUTC\":\"2022-10-10T16:09:41\",\"Sleep\":50,\"CfgHolder\":4617,\"BootCount\":22,\"BCResetTime\":\"2022-01-27T16:10:56\",\"SaveCount\":1235,\"SaveAddress\":\"F9000\"},\"StatusFWR\":{\"Version\":\"10.1.0(tasmota)\",\"BuildDateTime\":\"2021-12-08T14:47:33\",\"Boot\":7,\"Core\":\"2_7_4_9\",\"SDK\":\"2.2.2-dev(38a443e)\",\"CpuFrequency\":80,\"Hardware\":\"ESP8266EX\",\"CR\":\"465/699\"},\"StatusLOG\":{\"SerialLog\":2,\"WebLog\":2,\"MqttLog\":0,\"SysLog\":0,\"LogHost\":\"\",\"LogPort\":514,\"SSId\":[\"DLINK_FastNet\",\"\"],\"TelePeriod\":300,\"Resolution\":\"558180C0\",\"SetOption\":[\"000A8009\",\"2805C80001000600003C5A0A000000000000\",\"00000280\",\"00006008\",\"00004000\"]},\"StatusMEM\":{\"ProgramSize\":616,\"Free\":384,\"Heap\":25,\"ProgramFlashSize\":1024,\"FlashSize\":2048,\"FlashChipId\":\"1540A1\",\"FlashFrequency\":40,\"FlashMode\":3,\"Features\":[\"00000809\",\"8FDAC787\",\"04368001\",\"000000CF\",\"010013C0\",\"C000F981\",\"00004004\",\"00001000\",\"00000020\"],\"Drivers\":\"1,2,3,4,5,6,7,8,9,10,12,16,18,19,20,21,22,24,26,27,29,30,35,37,45\",\"Sensors\":\"1,2,3,4,5,6\"},\"StatusNET\":{\"Hostname\":\"tasmota-D79E2C-7724\",\"IPAddress\":\"192.168.0.104\",\"Gateway\":\"192.168.0.1\",\"Subnetmask\":\"255.255.255.0\",\"DNSServer1\":\"192.168.0.1\",\"DNSServer2\":\"0.0.0.0\",\"Mac\":\"10:52:1C:D7:9E:2C\",\"Webserver\":2,\"HTTP_API\":1,\"WifiConfig\":4,\"WifiPower\":17.0},\"StatusMQT\":{\"MqttHost\":\"192.168.0.113\",\"MqttPort\":1883,\"MqttClientMask\":\"core-mosquitto\",\"MqttClient\":\"core-mosquitto\",\"MqttUser\":\"homeassistant\",\"MqttCount\":23,\"MAX_PACKET_SIZE\":1200,\"KEEPALIVE\":30,\"SOCKET_TIMEOUT\":4},\"StatusTIM\":{\"UTC\":\"2022-11-09T19:52:58\",\"Local\":\"2022-11-09T20:52:58\",\"StartDST\":\"2022-03-27T02:00:00\",\"EndDST\":\"2022-10-30T03:00:00\",\"Timezone\":\"+01:00\",\"Sunrise\":\"07:50\",\"Sunset\":\"17:17\"},\"StatusSNS\":{\"Time\":\"2022-11-09T20:52:58\"},\"StatusSTS\":{\"Time\":\"2022-11-09T20:52:58\",\"Uptime\":\"30T03:43:17\",\"UptimeSec\":2605397,\"Heap\":25,\"SleepMode\":\"Dynamic\",\"Sleep\":10,\"LoadAvg\":99,\"MqttCount\":23,\"POWER\":\"ON\",\"Dimmer\":99,\"Fade\":\"OFF\",\"Speed\":1,\"LedTable\":\"ON\",\"Wifi\":{\"AP\":1,\"SSId\":\"DLINK_FastNet\",\"BSSId\":\"30:B5:C2:5D:70:72\",\"Channel\":11,\"Mode\":\"11n\",\"RSSI\":80,\"Signal\":-60,\"LinkCount\":21,\"Downtime\":\"0T06:13:34\"}}}";
+ printer(request, dbg);
+ return;
+
+#endif
+
+ bRelayIndexingStartsWithZero = CHANNEL_HasChannelPinWithRoleOrRole(0, IOR_Relay, IOR_Relay_n);
+
+ get_Relay_PWM_Count(&relayCount, &pwmCount, &dInputCount);
+
+ if (LED_IsLEDRunning()) {
+ powerCode = LED_GetEnableAll();
+ }
+ else {
+ powerCode = 0;
+ for (i = 0; i < CHANNEL_MAX; i++) {
+ bool bRelay;
+ int useIdx;
+ int iValue;
+ if (bRelayIndexingStartsWithZero) {
+ useIdx = i;
+ }
+ else {
+ useIdx = i + 1;
+ }
+ bRelay = CHANNEL_HasChannelPinWithRoleOrRole(useIdx, IOR_Relay, IOR_Relay_n);
+ if (bRelay) {
+ iValue = CHANNEL_Get(useIdx);
+ if (iValue)
+ BIT_SET(powerCode, i);
+ else
+ BIT_CLEAR(powerCode, i);
+ }
+ }
+ }
+
+ printer(request, "{");
+ // Status section
+ printer(request, "\"Status\":{\"Module\":0,\"DeviceName\":\"%s\"", deviceName);
+ printer(request, ",\"FriendlyName\":[");
+ if (relayCount == 0) {
+ printer(request, "\"%s\"", deviceName);
+ }
+ else {
+ int c_printed = 0;
+ for (i = 0; i < CHANNEL_MAX; i++) {
+ bool bRelay;
+ bRelay = CHANNEL_HasChannelPinWithRoleOrRole(i, IOR_Relay, IOR_Relay_n);
+ if (bRelay) {
+ int useIdx;
+ if (bRelayIndexingStartsWithZero) {
+ useIdx = i + 1;
+ }
+ else {
+ useIdx = i;
+ }
+ if (c_printed) {
+ printer(request, ",");
+ }
+ printer(request, "\"%s_%i\"", deviceName, useIdx);
+ c_printed++;
+ }
+ }
+ }
+ printer(request, "]");
+ printer(request, ",\"Topic\":\"%s\",\"ButtonTopic\":\"0\"", clientId);
+ printer(request, ",\"Power\":%i,\"PowerOnState\":3,\"LedState\":1", powerCode);
+ printer(request, ",\"LedMask\":\"FFFF\",\"SaveData\":1,\"SaveState\":1");
+ printer(request, ",\"SwitchTopic\":\"0\",\"SwitchMode\":[0,0,0,0,0,0,0,0]");
+ printer(request, ",\"ButtonRetain\":0,\"SwitchRetain\":0,\"SensorRetain\":0");
+ printer(request, ",\"PowerRetain\":0,\"InfoRetain\":0,\"StateRetain\":0");
+ printer(request, "}");
+
+ printer(request, ",");
+
+
+ printer(request, "\"StatusPRM\":{");
+ printer(request, "\"Baudrate\":115200,");
+ printer(request, "\"SerialConfig\":\"8N1\",");
+ printer(request, "\"GroupTopic\":\"tasmotas\",");
+ printer(request, "\"OtaUrl\":\"http://ota.tasmota.com/tasmota/release/tasmota.bin.gz\",");
+ printer(request, "\"RestartReason\":\"HardwareWatchdog\",");
+ printer(request, "\"Uptime\":\"30T02:59:30\",");
+ printer(request, "\"StartupUTC\":\"2022-10-10T16:09:41\",");
+ printer(request, "\"Sleep\":50,");
+ printer(request, "\"CfgHolder\":4617,");
+ printer(request, "\"BootCount\":22,");
+ printer(request, "\"BCResetTime\":\"2022-01-27T16:10:56\",");
+ printer(request, "\"SaveCount\":1235,");
+ printer(request, "\"SaveAddress\":\"F9000\"");
+ printer(request, "}");
+
+ printer(request, ",");
+
+ printer(request, "\"StatusFWR\":{");
+ printer(request, "\"Version\":\"%s\",", DEVICENAME_PREFIX_FULL"_"USER_SW_VER);
+ printer(request, "\"BuildDateTime\":\"%s\",", __DATE__ " " __TIME__);
+ printer(request, "\"Boot\":7,");
+ printer(request, "\"Core\":\"%s\",", "0.0");
+ printer(request, "\"SDK\":\"\",", "obk");
+ printer(request, "\"CpuFrequency\":80,");
+ printer(request, "\"Hardware\":\"%s\",", PLATFORM_MCU_NAME);
+ printer(request, "\"CR\":\"465/699\"");
+ printer(request, "}");
+
+ printer(request, ",");
+
+
+
+ printer(request, "\"StatusLOG\":{");
+ printer(request, "\"SerialLog\":2,");
+ printer(request, "\"WebLog\":2,");
+ printer(request, "\"MqttLog\":0,");
+ printer(request, "\"SysLog\":0,");
+ printer(request, "\"LogHost\":\"\",");
+ printer(request, "\"LogPort\":514,");
+ printer(request, "\"SSId\":[");
+ printer(request, "\"%s\",", CFG_GetWiFiSSID());
+ printer(request, "\"\"");
+ printer(request, "],");
+ printer(request, "\"TelePeriod\":300,");
+ printer(request, "\"Resolution\":\"558180C0\",");
+ printer(request, "\"SetOption\":[");
+ printer(request, "\"000A8009\",");
+ printer(request, "\"2805C80001000600003C5A0A000000000000\",");
+ printer(request, "\"00000280\",");
+ printer(request, "\"00006008\",");
+ printer(request, "\"00004000\"");
+ printer(request, "]");
+ printer(request, "}");
+
+ printer(request, ",");
+
+
+
+ printer(request, "\"StatusMEM\":{");
+ printer(request, "\"ProgramSize\":616,");
+ printer(request, "\"Free\":384,");
+ printer(request, "\"Heap\":25,");
+ printer(request, "\"ProgramFlashSize\":1024,");
+ printer(request, "\"FlashSize\":2048,");
+ printer(request, "\"FlashChipId\":\"1540A1\",");
+ printer(request, "\"FlashFrequency\":40,");
+ printer(request, "\"FlashMode\":3,");
+ printer(request, "\"Features\":[");
+ printer(request, "\"00000809\",");
+ printer(request, "\"8FDAC787\",");
+ printer(request, "\"04368001\",");
+ printer(request, "\"000000CF\",");
+ printer(request, "\"010013C0\",");
+ printer(request, "\"C000F981\",");
+ printer(request, "\"00004004\",");
+ printer(request, "\"00001000\",");
+ printer(request, "\"00000020\"");
+ printer(request, "],");
+ printer(request, "\"Drivers\":\"1,2,3,4,5,6,7,8,9,10,12,16,18,19,20,21,22,24,26,27,29,30,35,37,45\",");
+ printer(request, "\"Sensors\":\"1,2,3,4,5,6\"");
+ printer(request, "}");
+
+ printer(request, ",");
+
+
+ printer(request, "\"StatusNET\":{");
+ printer(request, "\"Hostname\":\"%s\",", CFG_GetShortDeviceName());
+ printer(request, "\"IPAddress\":\"%s\",", HAL_GetMyIPString());
+ printer(request, "\"Gateway\":\"192.168.0.1\",");
+ printer(request, "\"Subnetmask\":\"255.255.255.0\",");
+ printer(request, "\"DNSServer1\":\"192.168.0.1\",");
+ printer(request, "\"DNSServer2\":\"0.0.0.0\",");
+ printer(request, "\"Mac\":\"10:52:1C:D7:9E:2C\",");
+ printer(request, "\"Webserver\":2,");
+ printer(request, "\"HTTP_API\":1,");
+ printer(request, "\"WifiConfig\":4,");
+ printer(request, "\"WifiPower\":17.0");
+ printer(request, "}");
+ printer(request, ",");
+
+
+
+
+ printer(request, "\"StatusMQT\":{");
+ printer(request, "\"MqttHost\":\"%s\",", CFG_GetMQTTHost());
+ printer(request, "\"MqttPort\":%i,", CFG_GetMQTTPort());
+ printer(request, "\"MqttClientMask\":\"core-mosquitto\",");
+ printer(request, "\"MqttClient\":\"%s\",", CFG_GetMQTTClientId());
+ printer(request, "\"MqttUser\":\"%s\",", CFG_GetMQTTUserName());
+ printer(request, "\"MqttCount\":23,");
+ printer(request, "\"MAX_PACKET_SIZE\":1200,");
+ printer(request, "\"KEEPALIVE\":30,");
+ printer(request, "\"SOCKET_TIMEOUT\":4");
+ printer(request, "}");
+
+ printer(request, ",");
+ time_t localTime = (time_t)NTP_GetCurrentTime();
+ {
+ time_t localUTC = (time_t)NTP_GetCurrentTimeWithoutOffset();
+
+ printer(request, "\"StatusTIM\":{");
+ strftime(buff, sizeof(buff), "%Y-%m-%dT%H:%M:%S", localtime(&localUTC));
+ printer(request, "\"UTC\":\"%s\",", buff);
+ strftime(buff, sizeof(buff), "%Y-%m-%dT%H:%M:%S", localtime(&localTime));
+ printer(request, "\"Local\":\"%s\",", buff);
+ printer(request, "\"StartDST\":\"2022-03-27T02:00:00\",");
+ printer(request, "\"EndDST\":\"2022-10-30T03:00:00\",");
+ printer(request, "\"Timezone\":\"+01:00\",");
+ printer(request, "\"Sunrise\":\"07:50\",");
+ printer(request, "\"Sunset\":\"17:17\"");
+ printer(request, "}");
+ }
+
+ printer(request, ",");
+
+
+ http_tasmota_json_status_SNS(request, printer);
+
+ printer(request, ",");
+
+ printer(request, "\"StatusSTS\":");
+
+ http_tasmota_json_status_STS(request, printer);
+
+ // end
+ printer(request, "}");
+
+
+
+ return 0;
+}
+// TODO: move it somewhere else?
+void MQTT_PublishPrinterContentsToStat(struct obk_mqtt_publishReplyPrinter_s *printer, const char *statName);
+int JSON_ProcessCommandReply(const char *cmd, void *request, jsonCb_t printer, int flags) {
+
+ if (!wal_strnicmp(cmd, "POWER", 5)) {
+
+ printer(request, "{");
+ http_tasmota_json_power(request, printer, flags);
+ printer(request, "}");
+ if (flags == COMMAND_FLAG_SOURCE_MQTT) {
+ MQTT_PublishPrinterContentsToStat((struct obk_mqtt_publishReplyPrinter_s *)request, "RESULT");
+ }
+ }
+ else if (!wal_strnicmp(cmd, "STATUS 8", 8) || !wal_strnicmp(cmd, "STATUS 10", 10)) {
+ printer(request, "{");
+ http_tasmota_json_status_SNS(request, printer);
+ printer(request, "}");
+ if (flags == COMMAND_FLAG_SOURCE_MQTT) {
+ MQTT_PublishPrinterContentsToStat((struct obk_mqtt_publishReplyPrinter_s *)request, "STATUS");
+ }
+ }
+ else if (!wal_strnicmp(cmd, "STATUS", 6)) {
+ http_tasmota_json_status_generic(request, printer);
+ if (flags == COMMAND_FLAG_SOURCE_MQTT) {
+ MQTT_PublishPrinterContentsToStat((struct obk_mqtt_publishReplyPrinter_s *)request, "STATUS");
+ }
+ }
+
+ return 0;
+}
+
+
+
diff --git a/src/mqtt/new_mqtt.c b/src/mqtt/new_mqtt.c
index 45c11adef..4277babe7 100644
--- a/src/mqtt/new_mqtt.c
+++ b/src/mqtt/new_mqtt.c
@@ -637,8 +637,53 @@ int channelSet(obk_mqtt_request_t* request) {
// Payload: echo Test1; power toggle; echo Test2
// will do echo, toggle power and do ecoh
//
+#define MQTT_STACK_BUFFER_SIZE 32
+#define MQTT_TOTAL_BUFFER_SIZE 4096
+typedef struct obk_mqtt_publishReplyPrinter_s {
+ char *allocated;
+ char stackBuffer[MQTT_STACK_BUFFER_SIZE];
+ int curLen;
+} obk_mqtt_publishReplyPrinter_t;
+
+void MQTT_PublishPrinterContentsToStat(struct obk_mqtt_publishReplyPrinter_s *printer, const char *statName) {
+ const char *toUse;
+ if (printer->allocated)
+ toUse = printer->allocated;
+ else
+ toUse = printer->stackBuffer;
+ MQTT_PublishStat(statName, toUse);
+}
+int mqtt_printf255(obk_mqtt_publishReplyPrinter_t* request, const char* fmt, ...) {
+ va_list argList;
+ char tmp[256];
+ int myLen;
+
+ memset(tmp, 0, sizeof(tmp));
+ va_start(argList, fmt);
+ vsnprintf(tmp, 255, fmt, argList);
+ va_end(argList);
+
+ myLen = strlen(tmp);
+
+ if (request->curLen + (myLen+2) >= MQTT_STACK_BUFFER_SIZE) {
+ // init alloced if needed
+ if (request->allocated == 0) {
+ request->allocated = malloc(MQTT_TOTAL_BUFFER_SIZE);
+ strcpy(request->allocated, request->stackBuffer);
+ }
+ strcat(request->allocated, tmp);
+ }
+ else {
+ strcat(request->stackBuffer, tmp);
+ }
+ request->curLen += myLen;
+}
int tasCmnd(obk_mqtt_request_t* request) {
- const char* p = request->topic;
+ const char *p, *args;
+
+ obk_mqtt_publishReplyPrinter_t replyBuilder;
+ memset(&replyBuilder, 0, sizeof(obk_mqtt_publishReplyPrinter_t));
+ p = request->topic;
// TODO: better
// skip to after second forward slash
while (*p != '/') { if (*p == 0) return 0; p++; }
@@ -647,10 +692,15 @@ int tasCmnd(obk_mqtt_request_t* request) {
p++;
#if 1
+ args = (const char *)request->received;
// I think that our function get_received always ensured that
// there is a NULL terminating character after payload of MQTT
// So we can feed it directly as command
- CMD_ExecuteCommandArgs(p, (const char *)request->received, COMMAND_FLAG_SOURCE_MQTT);
+ CMD_ExecuteCommandArgs(p, args, COMMAND_FLAG_SOURCE_MQTT);
+ JSON_ProcessCommandReply(p, &replyBuilder, mqtt_printf255, COMMAND_FLAG_SOURCE_MQTT);
+ if (replyBuilder.allocated != 0) {
+ free(replyBuilder.allocated);
+ }
#else
int len = request->receivedLen;
char copy[64];
@@ -816,7 +866,12 @@ static OBK_Publish_Result MQTT_PublishMain(mqtt_client_t* client, const char* sC
{
return MQTT_PublishTopicToClient(mqtt_client, CFG_GetMQTTClientId(), sChannel, sVal, flags, appendGet);
}
-
+OBK_Publish_Result MQTT_PublishStat(const char* statName, const char* statValue)
+{
+ char topic[64];
+ snprintf(topic,sizeof(topic),"stat/%s", CFG_GetMQTTClientId());
+ return MQTT_PublishTopicToClient(mqtt_client, topic, statName, statValue, 0, false);
+}
/// @brief Publish a MQTT message immediately.
/// @param sTopic
/// @param sChannel
diff --git a/src/mqtt/new_mqtt.h b/src/mqtt/new_mqtt.h
index 4abff508d..276f334af 100644
--- a/src/mqtt/new_mqtt.h
+++ b/src/mqtt/new_mqtt.h
@@ -139,6 +139,7 @@ void MQTT_PublishOnlyDeviceChannelsIfPossible();
void MQTT_QueuePublish(const char* topic, const char* channel, const char* value, int flags);
void MQTT_QueuePublishWithCommand(const char* topic, const char* channel, const char* value, int flags, PostPublishCommands command);
OBK_Publish_Result MQTT_Publish(const char* sTopic, const char* sChannel, const char* value, int flags);
+OBK_Publish_Result MQTT_PublishStat(const char* statName, const char* statValue);
void MQTT_InvokeCommandAtEnd(PostPublishCommands command);
bool MQTT_IsReady();
diff --git a/src/new_common.h b/src/new_common.h
index f237df9ae..781573243 100644
--- a/src/new_common.h
+++ b/src/new_common.h
@@ -424,5 +424,10 @@ extern int bSafeMode;
extern int g_timeSinceLastPingReply;
extern int g_startPingWatchDogAfter;
+
+typedef int(*jsonCb_t)(void *userData, const char *fmt, ...);
+int JSON_ProcessCommandReply(const char *cmd, void *request, jsonCb_t printer, int flags);
+
+
#endif /* __NEW_COMMON_H__ */
diff --git a/src/selftest/selftest_tasmota.c b/src/selftest/selftest_tasmota.c
index c5b87d3ec..b470c6de2 100644
--- a/src/selftest/selftest_tasmota.c
+++ b/src/selftest/selftest_tasmota.c
@@ -6,9 +6,14 @@ void Test_Tasmota_MQTT_Switch() {
SIM_ClearOBK();
SIM_ClearAndPrepareForMQTTTesting("miscDevice");
+ const char *my_full_device_name = "TestingDevMQTTSwitch";
+ CFG_SetDeviceName(my_full_device_name);
+
PIN_SetPinRoleForPinIndex(9, IOR_Relay);
PIN_SetPinChannelForPinIndex(9, 1);
+ CMD_ExecuteCommand("setChannel 1 0", 0);
+ SELFTEST_ASSERT_CHANNEL(1, 0);
/*
// If single power
cmnd/tasmota_switch/Power ? // an empty message/payload sends a status query
@@ -16,6 +21,18 @@ void Test_Tasmota_MQTT_Switch() {
? stat/tasmota_switch/POWER ? OFF
*/
SIM_SendFakeMQTTAndRunSimFrame_CMND("Power", "");
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT("stat/miscDevice/RESULT", false);
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "POWER", "OFF");
+ SIM_ClearMQTTHistory();
+
+ CMD_ExecuteCommand("setChannel 1 1", 0);
+ SELFTEST_ASSERT_CHANNEL(1, 1);
+
+ SIM_SendFakeMQTTAndRunSimFrame_CMND("Power", "");
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT("stat/miscDevice/RESULT", false);
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "POWER", "ON");
+ SIM_ClearMQTTHistory();
+
/*
// If multiple power
cmnd/tasmota_switch/Power1 ? // an empty message/payload sends a status query
@@ -30,8 +47,60 @@ void Test_Tasmota_MQTT_Switch() {
? stat/tasmota_switch/RESULT ? {"POWER":"ON"}
? stat/tasmota_switch/POWER ? ON
*/
+ SELFTEST_ASSERT_CHANNEL(1, 1);
+ SIM_ClearMQTTHistory();
SIM_SendFakeMQTTAndRunSimFrame_CMND("Power", "Toggle");
+ SELFTEST_ASSERT_CHANNEL(1, 0);
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT("stat/miscDevice/RESULT", false);
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "POWER", "OFF");
+ SIM_ClearMQTTHistory();
+ /*
+ // When send status, we get full status on stat
+ // cmnd/tasmota_787019/STATUS
+
+ Message 6 received on stat/tasmota_787019/STATUS at 10:36 AM:
+ {
+ "Status": {
+ "Module": 0,
+ "DeviceName": "TasmotaBathroom",
+ "FriendlyName": [
+ "TasmotaBathroom"
+ ],
+ "Topic": "tasmota_787019",
+ "ButtonTopic": "0",
+ "Power": 0,
+ "PowerOnState": 3,
+ "LedState": 1,
+ "LedMask": "FFFF",
+ "SaveData": 1,
+ "SaveState": 1,
+ "SwitchTopic": "0",
+ "SwitchMode": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "ButtonRetain": 0,
+ "SwitchRetain": 0,
+ "SensorRetain": 0,
+ "PowerRetain": 0,
+ "InfoRetain": 0,
+ "StateRetain": 0
+ }
+ }
+ */
+ SIM_ClearMQTTHistory();
+ SIM_SendFakeMQTTAndRunSimFrame_CMND("STATUS", "");
+ SELFTEST_ASSERT_CHANNEL(1, 0);
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT("stat/miscDevice/STATUS", false);
+ SELFTEST_ASSERT_JSON_VALUE_STRING("Status", "DeviceName", CFG_GetShortDeviceName());
+ SIM_ClearMQTTHistory();
}
@@ -60,12 +129,23 @@ void Test_Tasmota_MQTT_RGBCW() {
? stat/tasmota_rgbcw/RESULT ? {"POWER":"OFF"}
? stat/tasmota_switch/POWER ? OFF
*/
+ CMD_ExecuteCommand("led_enableAll 0", 0);
+ SIM_SendFakeMQTTAndRunSimFrame_CMND("Power", "");
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT("stat/rgbcwBulb/RESULT", false);
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "POWER", "OFF");
+ SIM_ClearMQTTHistory();
+ CMD_ExecuteCommand("led_enableAll 1", 0);
+
+ SIM_SendFakeMQTTAndRunSimFrame_CMND("Power", "");
+ SELFTEST_ASSERT_HAS_MQTT_JSON_SENT("stat/rgbcwBulb/RESULT", false);
+ SELFTEST_ASSERT_JSON_VALUE_STRING(0, "POWER", "ON");
+ SIM_ClearMQTTHistory();
/*
// Powers as for single relay, but also
cmnd/tasmota_rgbcw/CT 153
- gives
+ gives stat/tasmota_rgbcw/RESULT
{
"POWER": "ON",
"Dimmer": 100,
@@ -86,7 +166,7 @@ void Test_Tasmota_MQTT_RGBCW() {
/*
// Powers as for single relay, but also
cmnd/tasmota_rgbcw/CT
- gives
+ gives stat/tasmota_rgbcw/RESULT
{
"CT": 153
}
@@ -95,7 +175,7 @@ void Test_Tasmota_MQTT_RGBCW() {
/*
// Powers as for single relay, but also
cmnd/tasmota_rgbcw/HSBColor
- gives
+ gives stat/tasmota_rgbcw/RESULT
{
"POWER": "ON",
"Dimmer": 100,
@@ -115,7 +195,7 @@ void Test_Tasmota_MQTT_RGBCW() {
/*
// Powers as for single relay, but also
cmnd/tasmota_rgbcw/HSBColor 90,100,0
- gives
+ gives stat/tasmota_rgbcw/RESULT
{
"POWER": "ON",
"Dimmer": 100,
@@ -135,7 +215,7 @@ void Test_Tasmota_MQTT_RGBCW() {
/*
// Powers as for single relay, but also
cmnd/tasmota_rgbcw/Dimmer
- gives
+ gives stat/tasmota_rgbcw/RESULT
{
"Dimmer": 20
}
@@ -144,7 +224,7 @@ void Test_Tasmota_MQTT_RGBCW() {
/*
// Powers as for single relay, but also
cmnd/tasmota_rgbcw/Dimmer 20
- gives
+ gives stat/tasmota_rgbcw/RESULT
{
"POWER": "ON",
"Dimmer": 20,
@@ -164,7 +244,7 @@ void Test_Tasmota_MQTT_RGBCW() {
/*
// Powers as for single relay, but also
cmnd/tasmota_rgbcw/Dimmer 100
- gives
+ gives stat/tasmota_rgbcw/RESULT
{
"POWER": "ON",
"Dimmer": 100,