diff --git a/README.md b/README.md index 5f47760ab..743f9cbc8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## Sonoff-Tasmota Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE. -Current version is **5.8.0q** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information. +Current version is **5.9.0a** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information. ### ATTENTION All versions diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 3100cc6d8..49f545291 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,91 +1,11 @@ -/* 5.8.0q - * Shrink code by 4k using command lookup tables - * Add retry counter to DHT11/21/22 sensors (#1082) - * Add commands RfSync, RfLow, RfHigh, RfHost and RfCode to allow sending custom RF codes (#1001) +/* 5.9.0a + * Add external sensor function pointer interface to enable easy sensor addition + * Fix Backup Configuration file download failure by defining proper file size (#1115) * - * 5.8.0p - * Fix initial PwmFrequency and PwmRange - * Add support for Arilux AL-LC01 RGB Led controller (#370) - * Add light turn Off Fade (#925) - * Change IrSend Panasonic command to IrSend {"Protocol":"Panasonic", "Bits":16388, "Data":} - * where 16388 is 0x4004 hexadecimal (#1014) - * - * 5.8.0o - * Remove max string length of 14 for Domoticz sensor descriptions - * Add light scheme options (Color cycle Up, Down, Random) and moving WS2812 schemes up by 3 - * Add support for VEML6070 I2C Ultra Violet level sensor (#1053) - * - * 5.8.0n - * Fix minimum TelePeriod of 10 seconds set by web page - * Shrink information web page by 1k code space - * Removed Arduino IDE version too low warning as it interferes with platformio.ini platform = espressif8266_stage - * Add commands Color2, Color3, Color4, Width2, Width3, Width4 and SetOption16 to set Ws2812 Clock parameters (#1019) - * Fix Color3 and Color4 (#1019) - * Add Polish language file (#1044, #1047) - * Add support for KMC 70011 Power Monitoring Smart Plug (#1045) - * Corrected German language file (#1054) - * - * 5.8.0m + * 5.9.0 20171030 * Rewrite code (partly) using Google C++ Style Guide (https://google.github.io/styleguide/cppguide.html) - * Allow empty MqttHost name by using option 0 - * Allow Mqtt server mDNS lookup only when MqttHost name is empty (#1026) - * Change Ws2812 clock with more flexible version (#1019) - * Add German language file (#1022) - * Support connecting to MQTT brokers without userid and/or password (#1023) - * Add commands PwmRange 1,255..1023 and PwmFrequency 1,100..4000 (#1025) - * - * 5.8.0l - * Update HTML/CSS to enable nicer form field entry - * Fix inverted relay status after restart or power on as regression from 5.8.0d (#909) - * Add send protocol Panasonic to IRsend (#1014) - * Fix relay power control when light power control is also configured as regression from 5.8.0 (#1016) - * - * 5.8.0k - * Add support for up to 8 relays (#995) - * Fix Blocked Loop when erasing large flash using command reset 2 (#1002) - * Add retain to ENERGY messages controlled by command SensorRetain (#1013) - * - * 5.8.0j - * Set default altitude to 0 to be used with pressure sensors - * Document flash settings area for future use - * Prepare for 32-bit power control (#995) - * Introduce sonoff.h master header - * Fix TLS MQTT SSL fingerprint test (#808, #970) - * Fix pressure calculation for some BMP versions regression introduced with version 5.8.0i (#974) - * Fix Domoticz Dimmer set to same level not powering on (#945) - * - * 5.8.0i - * Add Domoticz counter sensor to IrReceive representing Received IR Protocol and Data - * Fix Southern Hemisphere TIME_STD/TIME_DST (#968) - * Add Sea level pressure calculation (#974) - * Fix virtual relay status message used with Color/Dimmer control (#989) - * Fix command IRSend and IRHvac case sensitive parameter regression introduced with version 5.8.0 (#993) - * - * 5.8.0h - * Rename command IRRemote to IRSend (#956) - * Add IR Receiver support. Disable in user_config.h (#956) - * Change default PWM assignment for Witty Cloud to support optional Color/Dimmer control (#976) - * GPIO12 (Green) from GPIO_PWM4 to GPIO_PWM2 - * GPIO13 (Blue) from GPIO_PWM5 to GPIO_PWM3 - * GPIO15 (Red) from GPIO_PWM3 to GPIO_PWM1 - * - * 5.8.0g - * Fix inverted PWM index (#960) - * Fix some PWM related issues (#967) - * Fix timezone range from -12/12 to -13/13 (#968) - * - * 5.8.0f - * Set all saved power settings to Off when SetOption0 (SaveState) = 0 (#955) - * Allow PWM initialization after restart (#955) - * Add support for inverted PWM (#960) - * - * 5.8.0e - * Add Domoticz counter sensor to Sonoff Bridge representing Received RF code (#943) - * Add support for Luani HVIO board (https://luani.de/projekte/esp8266-hvio/) (#953) - * - * 5.8.0d - * Remove previous GPIO configuration when another module is selected - * Fix inverted relay power on state (#909) + * Rewrite code by using command lookup tables and javascript (client side) web page expansions + * Change HTML/CSS to enable nicer form field entry * Change default PWM assignments for H801 RGB(CW) led controller to support optional Color/Dimmer control * GPIO04 (W2) from GPIO_PWM2 to GPIO_USER to be user configurable for GPIO_PWM5 (second White - Warm if W1 is Cold) * GPIO12 (Blue) GPIO_PWM3 no change @@ -97,26 +17,66 @@ * GPIO12 (Blue) from GPIO_PWM5 to GPIO_PWM3 * GPIO13 (White) GPIO_USER to be user configurable for GPIO_PWM4 (White - Cold or Warm) * GPIO14 (Red) from GPIO_PWM3 to GPIO_PWM1 - * Add command SetOption15 0 (default) for command PWM control or SetOption15 1 for commands Color/Dimmer control to PWM RGB(CW) leds (#941) - * - * 5.8.0c - * Add warning to webpage when USE_MINIMAL is selected (#929) - * Fix compile error when DOMOTICZ_UPDATE_TIMER is not defined (#930) - * Fix alignment of web page items in some browsers (#935) - * Add smoother movement of hour hand in WS2812 led clock (#936) - * Add support for Magic Home RGBW and some Arilux Led controllers (#940) - * - * 5.8.0b + * Change default PWM assignment for Witty Cloud to support optional Color/Dimmer control (#976) + * GPIO12 (Green) from GPIO_PWM4 to GPIO_PWM2 + * GPIO13 (Blue) from GPIO_PWM5 to GPIO_PWM3 + * GPIO15 (Red) from GPIO_PWM3 to GPIO_PWM1 + * Change when another module is selected now all GPIO user configuration is removed + * Change command name IRRemote to IRSend (#956) + * Remove Arduino IDE version too low warning as it interferes with platformio.ini platform = espressif8266_stage * Fix command FullTopic entry when using serial or console interface * Fix possible UDP syslog blocking + * Fix minimum TelePeriod of 10 seconds set by web page + * Fix command GPIOx JSON response (#897) + * Fix inverted relay power on state (#909) + * Fix compile error when DOMOTICZ_UPDATE_TIMER is not defined (#930) + * Fix alignment of web page items in some browsers (#935) + * Fix setting all saved power settings to Off when SetOption0 (SaveState) = 0 (#955) + * Fix timezone range from -12/12 to -13/13 (#968) + * Fix Southern Hemisphere TIME_STD/TIME_DST (#968) + * Fix TLS MQTT SSL fingerprint test (#970, #808) + * Fix virtual relay status message used with Color/Dimmer control (#989) + * Fix command IRSend and IRHvac case sensitive parameter regression introduced with version 5.8.0 (#993) + * Fix pressure calculation for some BMP versions regression introduced with version 5.8.0i (#974) + * Fix Domoticz Dimmer set to same level not powering on (#945) + * Fix Blocked Loop when erasing large flash using command reset 2 (#1002) + * Fix relay power control when light power control is also configured as regression from 5.8.0 (#1016) + * Fix Mqtt server mDNS lookup only when MqttHost name is empty (#1026) * Add debug information to MQTT subscribe - * Add Domoticz sensors for Voltage and Current (#903) - * - * 5.8.0a * Add translations to I2Cscan * Add translation to BH1750 unit lx - * Set default WS2812 pixel count to WS2812_LEDS - * Fix command GPIOx JSON response (#897) + * Add light scheme options (Color cycle Up, Down, Random) and moving WS2812 schemes up by 3 + * Add Domoticz counter sensor to IrReceive representing Received IR Protocol and Data + * Add option 0 to MqttHost to allow empty Mqtt host name + * Add support for Arilux AL-LC01 RGB Led controller (#370) + * Add esp8266 de-blocking to PubSubClient library (#790) + * Add Domoticz sensors for Voltage and Current (#903) + * Add platformio OTA upload support (#928, #934) + * Add warning to webpage when USE_MINIMAL is selected (#929) + * Add smoother movement of hour hand in WS2812 led clock (#936) + * Add support for Magic Home RGBW and some Arilux Led controllers (#940) + * Add command SetOption15 0 (default) for command PWM control or SetOption15 1 for commands Color/Dimmer control to PWM RGB(CW) leds (#941) + * Add Domoticz counter sensor to Sonoff Bridge representing Received RF code (#943) + * Add support for Luani HVIO board (https://luani.de/projekte/esp8266-hvio/) (#953) + * Add PWM initialization after restart (#955) + * Add IR Receiver support. Disable in user_config.h (#956) + * Add support for inverted PWM (#960) + * Add Sea level pressure calculation and Provide command Altitude (#974) + * Add support for up to 8 relays (#995) + * Add commands RfSync, RfLow, RfHigh, RfHost and RfCode to allow sending custom RF codes (#1001) + * Add retain to ENERGY messages controlled by command SensorRetain (#1013) + * Add commands Color2, Color3, Color4, Width2, Width3, Width4 and SetOption16 to set Ws2812 Clock parameters (#1019) + * Add German language file (#1022) + * Add support for connecting to MQTT brokers without userid and/or password (#1023) + * Add support for esp8266 core v2.4.0-rc2 (#1024) + * Add commands PwmRange 1,255..1023 and PwmFrequency 1,100..4000 (#1025) + * Add Polish language file (#1044, #1047) + * Add support for KMC 70011 Power Monitoring Smart Plug (#1045) + * Add support for VEML6070 I2C Ultra Violet level sensor (#1053) + * Add light turn Off Fade (#925) + * Add IrSend command option Panasonic as IrSend {"Protocol":"Panasonic", "Bits":16388, "Data":} + * where 16388 is 0x4004 hexadecimal (#1014) + * Add retry counter to DHT11/21/22 sensors (#1082) * * 5.8.0 20170918 * Remove the need for NeoPixelBus library for Hue support diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 603ba86f4..158339dbf 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -90,6 +90,8 @@ typedef unsigned long power_t; // Power (Relay) type #define APP_BAUDRATE 115200 // Default serial baudrate #define MAX_STATUS 11 // Max number of status lines +#define XSNS_MAX 20 // Max number of allowed Xsns External Sensors (Update xsns_interface.ino if changed) + /*********************************************************************************************\ * Enumeration \*********************************************************************************************/ @@ -110,6 +112,7 @@ enum Ws2812Color {WS_RED, WS_GREEN, WS_BLUE}; enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, LT_NU8, LT_NU9, LT_NU10, LT_WS2812, LT_RGBW, LT_RGBWC}; enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC}; enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; +enum XsnsFunctions {FUNC_XSNS_INIT, FUNC_XSNS_PREP, FUNC_XSNS_JSON, FUNC_XSNS_WEB}; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 542997939..c616f9e14 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05080011 // 5.8.0q +#define VERSION 0x05090001 // 5.9.0a // Location specific includes #include "sonoff.h" // Enumaration used in user_config.h @@ -183,6 +183,7 @@ uint8_t light_type = 0; // Light types boolean mdns_begun = false; +boolean (*xsns_func_ptr[XSNS_MAX])(byte); // External Sensor Function Pointers for simple implementation of sensors char version[16]; // Version string from VERSION define char my_hostname[33]; // Composed Wifi hostname char mqtt_client[33]; // Composed MQTT Clientname @@ -1757,9 +1758,8 @@ void PublishStatus(uint8_t payload) } if ((0 == payload) || (10 == payload)) { - uint8_t djson = 0; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS10_SENSOR "\":")); - MqttShowSensor(&djson); + MqttShowSensor(); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "10")); } @@ -1789,62 +1789,26 @@ void MqttShowState() mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.BSSIDstr().c_str()); } -void MqttShowSensor(uint8_t* djson) +boolean MqttShowSensor() { + boolean json_data_available = false; + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_TIME "\":\"%s\""), mqtt_data, GetDateAndTime().c_str()); for (byte i = 0; i < MAX_SWITCHES; i++) { if (pin[GPIO_SWT1 +i] < 99) { boolean swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_SWITCH "%d\":\"%s\""), mqtt_data, i +1, GetStateText(swm ^ lastwallswitch[i])); - *djson = 1; + json_data_available = true; } } - MqttShowCounter(djson); -#ifndef USE_ADC_VCC - if (pin[GPIO_ADC0] < 99) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_ANALOG_INPUT0 "\":%d"), mqtt_data, GetAdc0()); - *djson = 1; + if (XsnsCall(FUNC_XSNS_JSON)) { + json_data_available = true; } -#endif - if (SONOFF_SC == Settings.module) { - MqttShowSonoffSC(djson); - } - if (pin[GPIO_DSB] < 99) { -#ifdef USE_DS18B20 - MqttShowDs18b20(djson); -#endif // USE_DS18B20 -#ifdef USE_DS18x20 - MqttShowDs18x20(djson); -#endif // USE_DS18x20 - } -#ifdef USE_DHT - if (dht_flg) { - MqttShowDht(djson); - } -#endif // USE_DHT -#ifdef USE_I2C - if (i2c_flg) { -#ifdef USE_SHT - MqttShowSht(djson); -#endif // USE_SHT -#ifdef USE_HTU - MqttShowHtu(djson); -#endif // USE_HTU -#ifdef USE_BMP - MqttShowBmp(djson); -#endif // USE_BMP -#ifdef USE_BH1750 - MqttShowBh1750(djson); -#endif // USE_BH1750 -#ifdef USE_VEML6070 - MqttShowVeml6070(djson); -#endif // USE_VEML6070 -} -#endif // USE_I2C if (strstr_P(mqtt_data, PSTR(D_TEMPERATURE))) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_TEMPERATURE_UNIT "\":\"%c\""), mqtt_data, TempUnit()); } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + return json_data_available; } /********************************************************************************************/ @@ -1897,39 +1861,7 @@ void PerformEverySecond() if (Settings.tele_period) { tele_period++; if (tele_period == Settings.tele_period -1) { - if (pin[GPIO_DSB] < 99) { -#ifdef USE_DS18B20 - Ds18b20ReadTempPrep(); -#endif // USE_DS18B20 -#ifdef USE_DS18x20 - Ds18x20Search(); // Check for changes in sensors number - Ds18x20Convert(); // Start Conversion, takes up to one second -#endif // USE_DS18x20 - } -#ifdef USE_DHT - if (dht_flg) { - DhtReadPrep(); - } -#endif // USE_DHT -#ifdef USE_I2C - if (i2c_flg) { -#ifdef USE_SHT - ShtDetect(); -#endif // USE_SHT -#ifdef USE_HTU - HtuDetect(); -#endif // USE_HTU -#ifdef USE_BMP - BmpDetect(); -#endif // USE_BMP -#ifdef USE_BH1750 - Bh1750Detect(); -#endif // USE_BH1750 -#ifdef USE_VEML6070 - Veml6070Detect(); -#endif // USE_VEML6070 -} -#endif // USE_I2C + XsnsCall(FUNC_XSNS_PREP); } if (tele_period >= Settings.tele_period) { tele_period = 0; @@ -1938,10 +1870,8 @@ void PerformEverySecond() MqttShowState(); MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_STATE)); - uint8_t djson = 0; mqtt_data[0] = '\0'; - MqttShowSensor(&djson); - if (djson) { + if (MqttShowSensor()) { MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); } @@ -2684,24 +2614,9 @@ void GpioInit() #endif // USE_IR_RECEIVE #endif // USE_IR_REMOTE - CounterInit(); - hlw_flg = ((pin[GPIO_HLW_SEL] < 99) && (pin[GPIO_HLW_CF1] < 99) && (pin[GPIO_HLW_CF] < 99)); - if (hlw_flg) { - HlwInit(); - } -#ifdef USE_DHT - if (dht_flg) { - DhtInit(); - } -#endif // USE_DHT - -#ifdef USE_DS18x20 - if (pin[GPIO_DSB] < 99) { - Ds18x20Init(); - } -#endif // USE_DS18x20 + XSnsInit(); } extern "C" { diff --git a/sonoff/support.ino b/sonoff/support.ino index f48e2d1de..c0b99a6e5 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1136,16 +1136,6 @@ char TempUnit() return (Settings.flag.temperature_conversion) ? 'F' : 'C'; } -uint16_t GetAdc0() -{ - uint16_t alr = 0; - for (byte i = 0; i < 32; i++) { - alr += analogRead(A0); - delay(1); - } - return alr >> 5; -} - double FastPrecisePow(double a, double b) { // https://martin.ankerl.com/2012/01/25/optimized-approximative-pow-in-c-and-cpp/ @@ -1233,8 +1223,72 @@ int GetCommandCode(char* destination, size_t destination_size, const char* needl return result; } +#ifndef USE_ADC_VCC +/*********************************************************************************************\ + * ADC support +\*********************************************************************************************/ + +uint16_t GetAdc0() +{ + uint16_t alr = 0; + for (byte i = 0; i < 32; i++) { + alr += analogRead(A0); + delay(1); + } + return alr >> 5; +} + +boolean MqttShowAdc() +{ + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_ANALOG_INPUT0 "\":%d"), mqtt_data, GetAdc0()); + return true; +} + +#ifdef USE_WEBSERVER +void WebShowAdc() +{ + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{s}" D_ANALOG_INPUT0 "{m}%d{e}"), mqtt_data, GetAdc0()); +} +#endif // USE_WEBSERVER + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_02 + +boolean Xsns02(byte function) +{ + boolean result = false; + + if (pin[GPIO_ADC0] < 99) { + switch (function) { +// case FUNC_XSNS_INIT: +// break; +// case FUNC_XSNS_PREP: +// break; + case FUNC_XSNS_JSON: + result = MqttShowAdc(); + break; +#ifdef USE_WEBSERVER + case FUNC_XSNS_WEB: + WebShowAdc(); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_ADC_VCC + /*********************************************************************************************\ * Syslog + * + * Example: + * snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_LOG "Any value %d"), value); + * AddLog(LOG_LEVEL_DEBUG); + * \*********************************************************************************************/ void Syslog() diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 2c08a975b..671b07cea 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -197,4 +197,4 @@ #error "Select either USE_MQTT_TLS or USE_WEBSERVER as there is just not enough memory to play with" #endif -#endif // _USER_CONFIG_H_ \ No newline at end of file +#endif // _USER_CONFIG_H_ diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index d8f6dbfb9..df75b53dd 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -274,25 +274,19 @@ const char HTTP_TABLE100[] PROGMEM = ""; const char HTTP_COUNTER[] PROGMEM = "
"; -const char HTTP_SNS_TEMP[] PROGMEM = - ""; -const char HTTP_SNS_HUM[] PROGMEM = - ""; -const char HTTP_SNS_PRESSURE[] PROGMEM = - ""; -const char HTTP_SNS_PRESSUREATSEALEVEL[] PROGMEM = - ""; -const char HTTP_SNS_LIGHT[] PROGMEM = - ""; -const char HTTP_SNS_NOISE[] PROGMEM = - ""; -const char HTTP_SNS_DUST[] PROGMEM = - ""; const char HTTP_END[] PROGMEM = "" "" ""; +const char HTTP_ROW_START[] PROGMEM = ""; // Replaces {e} +const char HTTP_SNS_TEMP[] PROGMEM = "%s{s}%s " D_TEMPERATURE "{m}%s°%c{e}"; // {s} = +const char HTTP_SNS_HUM[] PROGMEM = "%s{s}%s " D_HUMIDITY "{m}%s%{e}"; // {s} = +const char HTTP_SNS_PRESSURE[] PROGMEM = "%s{s}%s " D_PRESSURE "{m}%s " D_UNIT_PRESSURE "{e}"; // {s} = +const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "%s{s}%s " D_PRESSUREATSEALEVEL "{m}%s " D_UNIT_PRESSURE "{e}"; // {s} = + const char HDR_CTYPE_PLAIN[] PROGMEM = "text/plain"; const char HDR_CTYPE_HTML[] PROGMEM = "text/html"; const char HDR_CTYPE_XML[] PROGMEM = "text/xml"; @@ -520,54 +514,13 @@ void HandleAjaxStatusRefresh() ExecuteCommand(svalue); } - String tpage = ""; - tpage += WebShowCounter(); -#ifndef USE_ADC_VCC - if (pin[GPIO_ADC0] < 99) { - snprintf_P(svalue, sizeof(svalue), PSTR(""), GetAdc0()); - tpage += svalue; - } -#endif - if (hlw_flg) { - tpage += WebShowHlw(); - } - if (SONOFF_SC == Settings.module) { - tpage += WebShowSonoffSc(); - } -#ifdef USE_DS18B20 - if (pin[GPIO_DSB] < 99) { - tpage += WebShowDs18b20(); - } -#endif // USE_DS18B20 -#ifdef USE_DS18x20 - if (pin[GPIO_DSB] < 99) { - tpage += WebShowDs18x20(); - } -#endif // USE_DS18x20 -#ifdef USE_DHT - if (dht_flg) { - tpage += WebShowDht(); - } -#endif // USE_DHT -#ifdef USE_I2C - if (i2c_flg) { -#ifdef USE_SHT - tpage += WebShowSht(); -#endif -#ifdef USE_HTU - tpage += WebShowHtu(); -#endif -#ifdef USE_BMP - tpage += WebShowBmp(); -#endif -#ifdef USE_BH1750 - tpage += WebShowBh1750(); -#endif -#ifdef USE_VEML6070 - tpage += WebShowVeml6070(); -#endif -} -#endif // USE_I2C + mqtt_data[0] = '\0'; + XsnsCall(FUNC_XSNS_WEB); + String tpage = mqtt_data; + tpage.replace(F("{s}"), FPSTR(HTTP_ROW_START)); // = + String page = ""; if (tpage.length() > 0) { page += FPSTR(HTTP_TABLE100); @@ -978,14 +931,14 @@ void HandleBackupConfiguration() uint8_t buffer[sizeof(Settings)]; WiFiClient myClient = WebServer->client(); - WebServer->setContentLength(4096); + WebServer->setContentLength(sizeof(buffer)); char attachment[100]; snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), Settings.friendlyname[0], version); WebServer->sendHeader(F("Content-Disposition"), attachment); WebServer->send(200, FPSTR(HDR_CTYPE_STREAM), ""); - memcpy(buffer, &Settings, sizeof(Settings)); + memcpy(buffer, &Settings, sizeof(buffer)); buffer[0] = CONFIG_FILE_SIGN; buffer[1] = (!CONFIG_FILE_XOR)?0:1; if (buffer[1]) { diff --git a/sonoff/xsns_counter.ino b/sonoff/xsns_01_counter.ino similarity index 78% rename from sonoff/xsns_counter.ino rename to sonoff/xsns_01_counter.ino index 5712da198..a2cfe2c24 100644 --- a/sonoff/xsns_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -85,9 +85,10 @@ void CounterInit() * Presentation \*********************************************************************************************/ -void MqttShowCounter(uint8_t* djson) +boolean MqttShowCounter() { char stemp[16]; + boolean json_data_available = false; byte dsxflg = 0; for (byte i = 0; i < MAX_COUNTERS; i++) { @@ -99,7 +100,7 @@ void MqttShowCounter(uint8_t* djson) dtostrfd(RtcSettings.pulse_counter[i], 0, stemp); } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_COUNTER "%d\":%s"), mqtt_data, i +1, stemp); - *djson = 1; + json_data_available = true; #ifdef USE_DOMOTICZ if (1 == dsxflg) { DomoticzSensor(DZ_COUNT, RtcSettings.pulse_counter[i]); @@ -108,17 +109,16 @@ void MqttShowCounter(uint8_t* djson) #endif // USE_DOMOTICZ } } + return json_data_available; } #ifdef USE_WEBSERVER const char HTTP_SNS_COUNTER[] PROGMEM = - ""; + "%s{s}" D_COUNTER "%d{m}%s%s{e}"; // {s} = -String WebShowCounter() +void WebShowCounter() { - String page = ""; char stemp[16]; - char sensor[80]; for (byte i = 0; i < MAX_COUNTERS; i++) { if (pin[GPIO_CNTR1 +i] < 99) { @@ -127,11 +127,36 @@ String WebShowCounter() } else { dtostrfi(RtcSettings.pulse_counter[i], 0, stemp); } - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_COUNTER, i+1, stemp, (bitRead(Settings.pulse_counter_type, i)) ? " " D_UNIT_SECOND : ""); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_COUNTER, mqtt_data, i +1, stemp, (bitRead(Settings.pulse_counter_type, i)) ? " " D_UNIT_SECOND : ""); } } - return page; } #endif // USE_WEBSERVER +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_01 + +boolean Xsns01(byte function) +{ + boolean result = false; + + switch (function) { + case FUNC_XSNS_INIT: + CounterInit(); + break; +// case FUNC_XSNS_PREP: +// break; + case FUNC_XSNS_JSON: + result = MqttShowCounter(); + break; +#ifdef USE_WEBSERVER + case FUNC_XSNS_WEB: + WebShowCounter(); + break; +#endif // USE_WEBSERVER + } + return result; +} diff --git a/sonoff/xsns_hlw8012.ino b/sonoff/xsns_03_hlw8012.ino similarity index 95% rename from sonoff/xsns_hlw8012.ino rename to sonoff/xsns_03_hlw8012.ino index 816b2c2ee..5fd18281a 100644 --- a/sonoff/xsns_hlw8012.ino +++ b/sonoff/xsns_03_hlw8012.ino @@ -718,15 +718,15 @@ void HlwMqttStatus() #ifdef USE_WEBSERVER const char HTTP_ENERGY_SNS[] PROGMEM = - "" - "" - "" - "" - "" - "" - ""; + "{s}" D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}" + "{s}" D_POWER_FACTOR "{m}%s{e}" + "{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; // {s} = -String WebShowHlw() +void WebShowHlw() { float total_energy; float daily_energy; @@ -742,7 +742,6 @@ String WebShowHlw() char scurrent[10]; char spower_factor[10]; char syesterday_energy[10]; - char sensor[400]; HlwReadEnergy(0, total_energy, daily_energy, energy, watts, voltage, current, power_factor); dtostrfi(total_energy, Settings.flag.energy_resolution, stotal_energy); @@ -752,7 +751,36 @@ String WebShowHlw() dtostrfi(current, 3, scurrent); dtostrfi(power_factor, 2, spower_factor); dtostrfi((float)Settings.hlw_kWhyesterday / 100000000, Settings.flag.energy_resolution, syesterday_energy); - snprintf_P(sensor, sizeof(sensor), HTTP_ENERGY_SNS, svoltage, scurrent, swatts, spower_factor, sdaily_energy, syesterday_energy, stotal_energy); - return String(sensor); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS, svoltage, scurrent, swatts, spower_factor, sdaily_energy, syesterday_energy, stotal_energy); } #endif // USE_WEBSERVER + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_03 + +boolean Xsns03(byte function) +{ + boolean result = false; + + if (hlw_flg) { + switch (function) { + case FUNC_XSNS_INIT: + HlwInit(); + break; +// case FUNC_XSNS_PREP: +// break; +// case FUNC_XSNS_JSON: +// result = MqttShowHlw(); +// break; +#ifdef USE_WEBSERVER + case FUNC_XSNS_WEB: + WebShowHlw(); + break; +#endif // USE_WEBSERVER + } + } + return result; +} diff --git a/sonoff/xdrv_snfsc.ino b/sonoff/xsns_04_snfsc.ino similarity index 77% rename from sonoff/xdrv_snfsc.ino rename to sonoff/xsns_04_snfsc.ino index 5cd50e45b..616d1ab66 100644 --- a/sonoff/xdrv_snfsc.ino +++ b/sonoff/xsns_04_snfsc.ino @@ -105,8 +105,10 @@ void SonoffScSerialInput(char *rcvstat) * Presentation \*********************************************************************************************/ -void MqttShowSonoffSC(uint8_t* djson) +boolean MqttShowSonoffSC() { + boolean json_data_available = false; + if (sc_value[0] > 0) { char stemp1[10]; char stemp2[10]; @@ -117,40 +119,62 @@ void MqttShowSonoffSC(uint8_t* djson) dtostrfd(h, Settings.flag.humidity_resolution, stemp2); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_TEMPERATURE "\":%s, \"" D_HUMIDITY "\":%s, \"" D_LIGHT "\":%d, \"" D_NOISE "\":%d, \"" D_AIRQUALITY "\":%d"), mqtt_data, stemp1, stemp2, sc_value[2], sc_value[3], sc_value[4]); - *djson = 1; + json_data_available = true; #ifdef USE_DOMOTICZ DomoticzTempHumSensor(stemp1, stemp2); DomoticzSensor(DZ_ILLUMINANCE, sc_value[2]); #endif // USE_DOMOTICZ } + return json_data_available; } #ifdef USE_WEBSERVER -String WebShowSonoffSc() -{ - String page = ""; +const char HTTP_SNS_SCPLUS[] PROGMEM = "%s" + "{s}" D_LIGHT "{m}%d%{e}" + "{s}" D_NOISE "{m}%d%{e}" + "{s}" D_AIR_QUALITY "{m}%d%{e}"; // {s} = +void WebShowSonoffSc() +{ if (sc_value[0] > 0) { char stemp[10]; - char sensor[80]; - char scstype[] = ""; float t = ConvertTemp(sc_value[1]); dtostrfi(t, Settings.flag.temperature_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, scstype, stemp, TempUnit()); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "", stemp, TempUnit()); float h = sc_value[0]; dtostrfi(h, Settings.flag.humidity_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, scstype, stemp); - page += sensor; - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_LIGHT, scstype, sc_value[2]); - page += sensor; - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_NOISE, scstype, sc_value[3]); - page += sensor; - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_DUST, scstype, sc_value[4]); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, "", stemp); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SCPLUS, mqtt_data, sc_value[2], sc_value[3], sc_value[4]); } - return page; } #endif // USE_WEBSERVER +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_04 + +boolean Xsns04(byte function) +{ + boolean result = false; + + if (SONOFF_SC == Settings.module) { + switch (function) { +// case FUNC_XSNS_INIT: +// break; +// case FUNC_XSNS_PREP: +// break; + case FUNC_XSNS_JSON: + result = MqttShowSonoffSC(); + break; +#ifdef USE_WEBSERVER + case FUNC_XSNS_WEB: + WebShowSonoffSc(); + break; +#endif // USE_WEBSERVER + } + } + return result; +} diff --git a/sonoff/xsns_ds18b20.ino b/sonoff/xsns_05_ds18b20.ino similarity index 85% rename from sonoff/xsns_ds18b20.ino rename to sonoff/xsns_05_ds18b20.ino index 5b003a6f6..5be5aa0da 100644 --- a/sonoff/xsns_ds18b20.ino +++ b/sonoff/xsns_05_ds18b20.ino @@ -185,38 +185,66 @@ boolean Ds18b20ReadTemperature(float &t) * Presentation \*********************************************************************************************/ -void MqttShowDs18b20(uint8_t* djson) +boolean MqttShowDs18b20() { char stemp1[10]; float t; + boolean json_data_available = false; if (Ds18b20ReadTemperature(t)) { // Check if read failed dtostrfd(t, Settings.flag.temperature_resolution, stemp1); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"DS18B20\":{\"" D_TEMPERATURE "\":%s}"), mqtt_data, stemp1); - *djson = 1; + json_data_available = true; #ifdef USE_DOMOTICZ DomoticzSensor(DZ_TEMP, stemp1); #endif // USE_DOMOTICZ } + return json_data_available; } #ifdef USE_WEBSERVER -String WebShowDs18b20() +void WebShowDs18b20() { - // Needs TelePeriod to refresh data (Do not do it here as it takes too much time) - String page = ""; float st; if (Ds18b20ReadTemperature(st)) { // Check if read failed char stemp[10]; - char sensor[80]; dtostrfi(st, Settings.flag.temperature_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, "DS18B20", stemp, TempUnit()); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "DS18B20", stemp, TempUnit()); } Ds18b20ReadTempPrep(); - return page; } #endif // USE_WEBSERVER + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_05 + +boolean Xsns05(byte function) +{ + boolean result = false; + + if (pin[GPIO_DSB] < 99) { + switch (function) { +// case FUNC_XSNS_INIT: +// break; + case FUNC_XSNS_PREP: + Ds18b20ReadTempPrep(); + break; + case FUNC_XSNS_JSON: + result = MqttShowDs18b20(); + break; +#ifdef USE_WEBSERVER + case FUNC_XSNS_WEB: + WebShowDs18b20(); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + #endif // USE_DS18B20 diff --git a/sonoff/xsns_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino similarity index 85% rename from sonoff/xsns_ds18x20.ino rename to sonoff/xsns_05_ds18x20.ino index 2733ba9ab..12d7d48f1 100644 --- a/sonoff/xsns_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -163,11 +163,12 @@ void Ds18x20Type(uint8_t sensor) } } -void MqttShowDs18x20(uint8_t* djson) +boolean MqttShowDs18x20() { char stemp1[10]; char stemp2[10]; float t; + boolean json_data_available = false; byte dsxflg = 0; for (byte i = 0; i < Ds18x20Sensors(); i++) { @@ -176,7 +177,7 @@ void MqttShowDs18x20(uint8_t* djson) dtostrfd(t, Settings.flag.temperature_resolution, stemp2); if (!dsxflg) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"DS18x20\":{"), mqtt_data); - *djson = 1; + json_data_available = true; stemp1[0] = '\0'; } dsxflg++; @@ -193,15 +194,14 @@ void MqttShowDs18x20(uint8_t* djson) if (dsxflg) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } + return json_data_available; } #ifdef USE_WEBSERVER -String WebShowDs18x20() +void WebShowDs18x20() { - String page = ""; char stemp[10]; char stemp2[16]; - char sensor[80]; float t; for (byte i = 0; i < Ds18x20Sensors(); i++) { @@ -209,13 +209,44 @@ String WebShowDs18x20() Ds18x20Type(i); dtostrfi(t, Settings.flag.temperature_resolution, stemp); snprintf_P(stemp2, sizeof(stemp2), PSTR("%s-%d"), ds18x20_types, i +1); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, stemp2, stemp, TempUnit()); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, stemp2, stemp, TempUnit()); } } Ds18x20Search(); // Check for changes in sensors number Ds18x20Convert(); // Start Conversion, takes up to one second - return page; } #endif // USE_WEBSERVER + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_05 + +boolean Xsns05(byte function) +{ + boolean result = false; + + if (pin[GPIO_DSB] < 99) { + switch (function) { + case FUNC_XSNS_INIT: + Ds18x20Init(); + break; + case FUNC_XSNS_PREP: + Ds18x20Search(); // Check for changes in sensors number + Ds18x20Convert(); // Start Conversion, takes up to one second + break; + case FUNC_XSNS_JSON: + result = MqttShowDs18x20(); + break; +#ifdef USE_WEBSERVER + case FUNC_XSNS_WEB: + WebShowDs18x20(); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + #endif // USE_DS18x20 diff --git a/sonoff/xsns_dht.ino b/sonoff/xsns_06_dht.ino similarity index 87% rename from sonoff/xsns_dht.ino rename to sonoff/xsns_06_dht.ino index cea2bf17f..a604c6d7e 100644 --- a/sonoff/xsns_dht.ino +++ b/sonoff/xsns_06_dht.ino @@ -222,12 +222,13 @@ void DhtInit() * Presentation \*********************************************************************************************/ -void MqttShowDht(uint8_t* djson) +boolean MqttShowDht() { char stemp1[10]; char stemp2[10]; float t; float h; + boolean json_data_available = false; byte dsxflg = 0; for (byte i = 0; i < dht_sensors; i++) { @@ -235,7 +236,7 @@ void MqttShowDht(uint8_t* djson) dtostrfd(t, Settings.flag.temperature_resolution, stemp1); dtostrfd(h, Settings.flag.humidity_resolution, stemp2); snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, Dht[i].stype, stemp1, stemp2); - *djson = 1; + json_data_available = true; #ifdef USE_DOMOTICZ if (!dsxflg) { DomoticzTempHumSensor(stemp1, stemp2); @@ -244,28 +245,56 @@ void MqttShowDht(uint8_t* djson) #endif // USE_DOMOTICZ } } + return json_data_available; } #ifdef USE_WEBSERVER -String WebShowDht() +void WebShowDht() { - String page = ""; char stemp[10]; - char sensor[80]; float t; float h; for (byte i = 0; i < dht_sensors; i++) { if (DhtReadTempHum(i, t, h)) { dtostrfi(t, Settings.flag.temperature_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, Dht[i].stype, stemp, TempUnit()); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, Dht[i].stype, stemp, TempUnit()); dtostrfi(h, Settings.flag.humidity_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, Dht[i].stype, stemp); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, Dht[i].stype, stemp); } } - return page; } #endif // USE_WEBSERVER + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_06 + +boolean Xsns06(byte function) +{ + boolean result = false; + + if (dht_flg) { + switch (function) { + case FUNC_XSNS_INIT: + DhtInit(); + break; + case FUNC_XSNS_PREP: + DhtReadPrep(); + break; + case FUNC_XSNS_JSON: + result = MqttShowDht(); + break; +#ifdef USE_WEBSERVER + case FUNC_XSNS_WEB: + WebShowDht(); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + #endif // USE_DHT diff --git a/sonoff/xsns_sht1x.ino b/sonoff/xsns_07_sht1x.ino similarity index 84% rename from sonoff/xsns_sht1x.ino rename to sonoff/xsns_07_sht1x.ino index 676671244..47691b7c9 100644 --- a/sonoff/xsns_sht1x.ino +++ b/sonoff/xsns_07_sht1x.ino @@ -184,12 +184,13 @@ boolean ShtDetect() * Presentation \*********************************************************************************************/ -void MqttShowSht(uint8_t* djson) +boolean MqttShowSht() { if (!sht_type) { - return; + return false; } + boolean json_data_available = false; float t; float h; @@ -200,36 +201,60 @@ void MqttShowSht(uint8_t* djson) dtostrfd(t, Settings.flag.temperature_resolution, stemp); dtostrfd(h, Settings.flag.humidity_resolution, shum); snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, "SHT1X", stemp, shum); - *djson = 1; + json_data_available = true; #ifdef USE_DOMOTICZ DomoticzTempHumSensor(stemp, shum); #endif // USE_DOMOTICZ } + return json_data_available; } #ifdef USE_WEBSERVER -String WebShowSht() +void WebShowSht() { float t; float h; - String page = ""; if (sht_type) { if (ShtReadTempHum(t, h)) { char stemp[10]; - char shum[10]; - char sensor[80]; dtostrfi(t, Settings.flag.temperature_resolution, stemp); - dtostrfi(h, Settings.flag.humidity_resolution, shum); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, "SHT1X", stemp, TempUnit()); - page += sensor; - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, "SHT1X", shum); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "SHT1X", stemp, TempUnit()); + dtostrfi(h, Settings.flag.humidity_resolution, stemp); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, "SHT1X", stemp); } } - return page; } #endif // USE_WEBSERVER + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_07 + +boolean Xsns07(byte function) +{ + boolean result = false; + + switch (function) { +// case FUNC_XSNS_INIT: +// break; + case FUNC_XSNS_PREP: + ShtDetect(); + break; + case FUNC_XSNS_JSON: + result = MqttShowSht(); + break; +#ifdef USE_WEBSERVER + case FUNC_XSNS_WEB: + WebShowSht(); + break; +#endif // USE_WEBSERVER + } + return result; +} + #endif // USE_SHT #endif // USE_I2C diff --git a/sonoff/xsns_htu21.ino b/sonoff/xsns_08_htu21.ino similarity index 89% rename from sonoff/xsns_htu21.ino rename to sonoff/xsns_08_htu21.ino index 5bffbab52..5d6cef07d 100644 --- a/sonoff/xsns_htu21.ino +++ b/sonoff/xsns_08_htu21.ino @@ -255,10 +255,10 @@ uint8_t HtuDetect() * Presentation \*********************************************************************************************/ -void MqttShowHtu(uint8_t* djson) +boolean MqttShowHtu() { if (!htu_type) { - return; + return false; } char stemp1[10]; @@ -270,33 +270,57 @@ void MqttShowHtu(uint8_t* djson) dtostrfd(t, Settings.flag.temperature_resolution, stemp1); dtostrfd(h, Settings.flag.humidity_resolution, stemp2); snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, htu_types, stemp1, stemp2); - *djson = 1; #ifdef USE_DOMOTICZ DomoticzTempHumSensor(stemp1, stemp2); #endif // USE_DOMOTICZ + return true; } #ifdef USE_WEBSERVER -String WebShowHtu() +void WebShowHtu() { - String page = ""; if (htu_type) { char stemp[10]; - char sensor[80]; float t_htu21 = HtuReadTemperature(); float h_htu21 = HtuReadHumidity(); h_htu21 = HtuCompensatedHumidity(h_htu21, t_htu21); dtostrfi(t_htu21, Settings.flag.temperature_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, htu_types, stemp, TempUnit()); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, htu_types, stemp, TempUnit()); dtostrfi(h_htu21, Settings.flag.humidity_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, htu_types, stemp); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, htu_types, stemp); } - return page; } #endif // USE_WEBSERVER + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_08 + +boolean Xsns08(byte function) +{ + boolean result = false; + + switch (function) { +// case FUNC_XSNS_INIT: +// break; + case FUNC_XSNS_PREP: + HtuDetect(); + break; + case FUNC_XSNS_JSON: + result = MqttShowHtu(); + break; +#ifdef USE_WEBSERVER + case FUNC_XSNS_WEB: + WebShowHtu(); + break; +#endif // USE_WEBSERVER + } + return result; +} + #endif // USE_HTU #endif // USE_I2C diff --git a/sonoff/xsns_bmp.ino b/sonoff/xsns_09_bmp.ino similarity index 93% rename from sonoff/xsns_bmp.ino rename to sonoff/xsns_09_bmp.ino index fd7b33f93..4c36a8461 100644 --- a/sonoff/xsns_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -411,10 +411,10 @@ boolean BmpDetect() * Presentation \*********************************************************************************************/ -void MqttShowBmp(uint8_t *djson) +boolean MqttShowBmp() { if (!bmp_type) { - return; + return false; } char temperature[10]; @@ -440,42 +440,64 @@ void MqttShowBmp(uint8_t *djson) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_TEMPERATURE "\":%s, \"" D_PRESSURE "\":%s%s}"), mqtt_data, bmp_types, temperature, pressure, (Settings.altitude != 0) ? sealevel : ""); } - *djson = 1; #ifdef USE_DOMOTICZ DomoticzTempHumPressureSensor(temperature, humidity, pressure); #endif // USE_DOMOTICZ + return true; } #ifdef USE_WEBSERVER -String WebShowBmp() +void WebShowBmp() { - String page = ""; if (bmp_type) { char stemp[10]; - char sensor[80]; double t = BmpReadTemperature(); double p = BmpReadPressure(); double h = BmpReadHumidity(); dtostrfi(t, Settings.flag.temperature_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, bmp_types, stemp, TempUnit()); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, bmp_types, stemp, TempUnit()); if (BME280_CHIPID == bmp_type) { dtostrfi(h, Settings.flag.humidity_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, bmp_types, stemp); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, bmp_types, stemp); } dtostrfi(p, Settings.flag.pressure_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_PRESSURE, bmp_types, stemp); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_PRESSURE, mqtt_data, bmp_types, stemp); if (Settings.altitude != 0) { dtostrfi(bmp_sealevel, Settings.flag.pressure_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_PRESSUREATSEALEVEL, bmp_types, stemp); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SEAPRESSURE, mqtt_data, bmp_types, stemp); } } - return page; } #endif // USE_WEBSERVER + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_09 + +boolean Xsns09(byte function) +{ + boolean result = false; + + switch (function) { +// case FUNC_XSNS_INIT: +// break; + case FUNC_XSNS_PREP: + BmpDetect(); + break; + case FUNC_XSNS_JSON: + result = MqttShowBmp(); + break; +#ifdef USE_WEBSERVER + case FUNC_XSNS_WEB: + WebShowBmp(); + break; +#endif // USE_WEBSERVER + } + return result; +} + #endif // USE_BMP #endif // USE_I2C diff --git a/sonoff/xsns_bh1750.ino b/sonoff/xsns_10_bh1750.ino similarity index 76% rename from sonoff/xsns_bh1750.ino rename to sonoff/xsns_10_bh1750.ino index 96b93c21c..49bd05e20 100644 --- a/sonoff/xsns_bh1750.ino +++ b/sonoff/xsns_10_bh1750.ino @@ -78,35 +78,59 @@ boolean Bh1750Detect() * Presentation \*********************************************************************************************/ -void MqttShowBh1750(uint8_t* djson) +boolean MqttShowBh1750() { if (!bh1750_type) { - return; + return false; } uint16_t l = Bh1750ReadLux(); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_ILLUMINANCE "\":%d}"), mqtt_data, bh1750_types, l); - *djson = 1; #ifdef USE_DOMOTICZ DomoticzSensor(DZ_ILLUMINANCE, l); #endif // USE_DOMOTICZ + return true; } #ifdef USE_WEBSERVER const char HTTP_SNS_ILLUMINANCE[] PROGMEM = - ""; + "%s{s}BH1750 " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = -String WebShowBh1750() +void WebShowBh1750() { - String page = ""; if (bh1750_type) { - char sensor[80]; - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_ILLUMINANCE, Bh1750ReadLux()); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ILLUMINANCE, mqtt_data, Bh1750ReadLux()); } - return page; } #endif // USE_WEBSERVER + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_10 + +boolean Xsns10(byte function) +{ + boolean result = false; + + switch (function) { +// case FUNC_XSNS_INIT: +// break; + case FUNC_XSNS_PREP: + Bh1750Detect(); + break; + case FUNC_XSNS_JSON: + result = MqttShowBh1750(); + break; +#ifdef USE_WEBSERVER + case FUNC_XSNS_WEB: + WebShowBh1750(); + break; +#endif // USE_WEBSERVER + } + return result; +} + #endif // USE_BH1750 #endif // USE_I2C - diff --git a/sonoff/xsns_veml6070.ino b/sonoff/xsns_11_veml6070.ino similarity index 75% rename from sonoff/xsns_veml6070.ino rename to sonoff/xsns_11_veml6070.ino index 0a62a7737..c66cf0b27 100644 --- a/sonoff/xsns_veml6070.ino +++ b/sonoff/xsns_11_veml6070.ino @@ -44,7 +44,7 @@ uint16_t Veml6070ReadUv() } uvi |= Wire.read(); - return uvi; + return uvi; } boolean Veml6070Detect() @@ -79,35 +79,60 @@ boolean Veml6070Detect() * Presentation \*********************************************************************************************/ -void MqttShowVeml6070(uint8_t* djson) +boolean MqttShowVeml6070() { if (!veml6070_type) { - return; + return false; } uint16_t uv = Veml6070ReadUv(); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_UV_LEVEL "\":%d}"), mqtt_data, veml6070_types, uv); - *djson = 1; #ifdef USE_DOMOTICZ DomoticzSensor(DZ_ILLUMINANCE, uv); #endif // USE_DOMOTICZ + return true; } #ifdef USE_WEBSERVER const char HTTP_SNS_ULTRAVIOLET[] PROGMEM = - ""; - -String WebShowVeml6070() + "%s{s}VEML6070 " D_UV_LEVEL "{m}%d{e}"; // {s} = + +void WebShowVeml6070() { - String page = ""; if (veml6070_type) { - char sensor[80]; - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_ULTRAVIOLET, Veml6070ReadUv()); - page += sensor; + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ULTRAVIOLET, mqtt_data, Veml6070ReadUv()); } - return page; } #endif // USE_WEBSERVER + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_11 + +boolean Xsns11(byte function) +{ + boolean result = false; + + switch (function) { +// case FUNC_XSNS_INIT: +// break; + case FUNC_XSNS_PREP: + Veml6070Detect(); + break; + case FUNC_XSNS_JSON: + result = MqttShowVeml6070(); + break; +#ifdef USE_WEBSERVER + case FUNC_XSNS_WEB: + WebShowVeml6070(); + break; +#endif // USE_WEBSERVER + } + return result; +} + #endif // USE_VEML6070 #endif // USE_I2C diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino new file mode 100644 index 000000000..a17d70a5f --- /dev/null +++ b/sonoff/xsns_interface.ino @@ -0,0 +1,141 @@ +/* + xsns_interface.ino - External sensor interface support for Sonoff-Tasmota + + Copyright (C) 2017 Theo Arends inspired by ESPEasy + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +void XSnsInit() +{ + byte x; + + for (x = 0; x < XSNS_MAX; x++) { + xsns_func_ptr[x] = NULL; + } + x = 0; + +#ifdef XSNS_01 + xsns_func_ptr[x++] = &Xsns01; +#endif + +#ifdef XSNS_02 + xsns_func_ptr[x++] = &Xsns02; +#endif + +#ifdef XSNS_03 + xsns_func_ptr[x++] = &Xsns03; +#endif + +#ifdef XSNS_04 + xsns_func_ptr[x++] = &Xsns04; +#endif + +#ifdef XSNS_05 + xsns_func_ptr[x++] = &Xsns05; +#endif + +#ifdef XSNS_06 + xsns_func_ptr[x++] = &Xsns06; +#endif + +#ifdef XSNS_07 + xsns_func_ptr[x++] = &Xsns07; +#endif + +#ifdef XSNS_08 + xsns_func_ptr[x++] = &Xsns08; +#endif + +#ifdef XSNS_09 + xsns_func_ptr[x++] = &Xsns09; +#endif + +#ifdef XSNS_10 + xsns_func_ptr[x++] = &Xsns10; +#endif + +#ifdef XSNS_11 + xsns_func_ptr[x++] = &Xsns11; +#endif + +#ifdef XSNS_12 + xsns_func_ptr[x++] = &Xsns12; +#endif + +#ifdef XSNS_13 + xsns_func_ptr[x++] = &Xsns13; +#endif + +#ifdef XSNS_14 + xsns_func_ptr[x++] = &Xsns14; +#endif + +#ifdef XSNS_15 + xsns_func_ptr[x++] = &Xsns15; +#endif + +#ifdef XSNS_16 + xsns_func_ptr[x++] = &Xsns16; +#endif + +#ifdef XSNS_17 + xsns_func_ptr[x++] = &Xsns17; +#endif + +#ifdef XSNS_18 + xsns_func_ptr[x++] = &Xsns18; +#endif + +#ifdef XSNS_19 + xsns_func_ptr[x++] = &Xsns19; +#endif + +#ifdef XSNS_20 + xsns_func_ptr[x++] = &Xsns20; +#endif + + XsnsCall(FUNC_XSNS_INIT); +} + +/*********************************************************************************************\ + * Function call to all or specific xsns +\*********************************************************************************************/ + +boolean XsnsCall(byte Function) +{ + boolean result = false; + + switch (Function) { + case FUNC_XSNS_INIT: + case FUNC_XSNS_PREP: + case FUNC_XSNS_WEB: + for (byte x = 0; x < XSNS_MAX; x++) { + if (xsns_func_ptr[x]) { + xsns_func_ptr[x](Function); + } + } + break; + case FUNC_XSNS_JSON: + for (byte x = 0; x < XSNS_MAX; x++) { + if (xsns_func_ptr[x]) { + if (xsns_func_ptr[x](Function)) { + result = true; + } + } + } + break; + } + return result; +}
%s " D_TEMPERATURE "%s°%c
%s " D_HUMIDITY "%s%
%s " D_PRESSURE "%s " D_UNIT_PRESSURE "
%s " D_PRESSUREATSEALEVEL "%s " D_UNIT_PRESSURE "
%s " D_LIGHT "%d%
%s " D_NOISE "%d%
%s " D_AIR_QUALITY "%d%
"; // Replaces {s} +const char HTTP_ROW_MIDDLE[] PROGMEM = ""; // Replases {m} +const char HTTP_ROW_END[] PROGMEM = "
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
" D_ANALOG_INPUT0 "%d
+ tpage.replace(F("{m}"), FPSTR(HTTP_ROW_MIDDLE)); // = + tpage.replace(F("{e}"), FPSTR(HTTP_ROW_END)); // =
" D_COUNTER "%d%s%s
, {m} = , {e} =
" D_VOLTAGE "%s " D_UNIT_VOLT "
" D_CURRENT "%s " D_UNIT_AMPERE "
" D_POWERUSAGE "%s " D_UNIT_WATT "
" D_POWER_FACTOR "%s
" D_ENERGY_TODAY "%s " D_UNIT_KILOWATTHOUR "
" D_ENERGY_YESTERDAY "%s " D_UNIT_KILOWATTHOUR "
" D_ENERGY_TOTAL "%s " D_UNIT_KILOWATTHOUR "
, {m} = , {e} =
, {m} = , {e} =
BH1750 " D_ILLUMINANCE "%d " D_UNIT_LUX "
, {m} = , {e} =
VEML6070 " D_UV_LEVEL "%d
, {m} = , {e} =