diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index b1417029e..7bf6d8aba 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,11 +1,17 @@ -/* 6.2.1.19 20181023 +/* 6.2.1.20 20181028 + * Add command SetOption35 0..255 (seconds) to delay mDNS initialization to control possible Wifi connect problems + * Add command SetOption53 0/1 to toggle gui display of Hostname and IP address (#1006, #2091) + * Add token %hostname% to command FullTopic (#3018) + * Add support for two BMP/BME sensors (#4195) + * + * 6.2.1.19 20181023 * Fix header file execution order by renaming user_config.h to my_user_config.h * Fix invalid JSON floating point result from nan (Not a Number) and inf (Infinity) into null (#4147) * Fix rule mqtt#connected trigger when mqtt is disabled (#4149) * Initial release of RF transceiving using library RcSwitch (#2702) * Change default OTA Url to http://thehackbox.org/tasmota/release/sonoff.bin (#4170) * Add Tuya Software Serial to support additional Tuya configurations (#4178) - * Add sonoff-basic.bin without most sensors + * Add define USE_BASIC for selecting image sonoff-basic without most sensors * * 6.2.1.18 20181019 * Add more API callbacks and document API.md diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 7e096f673..d91c66bda 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "h" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 6a783a45b..0c2ab9f6a 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "h" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 937464699..c5a3db324 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -1,3 +1,4 @@ + /* el-GR.h - localization for Greek - Greece for Sonoff-Tasmota @@ -537,7 +538,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 925080d3d..48641d0ff 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index d78c807da..a5d044985 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index bb32c2d2e..0e37d9990 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "h" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index d1aee3423..355fe8231 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 91b005e39..cbe52378d 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "ó" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 2ed03ca35..8449d250d 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index ca7be61af..afaf9d08a 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "h" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 3fd26f29b..686f5cc76 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "Godz" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index dceadf085..ef5104fdb 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "H" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index a7b9236ae..97750f38c 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index fc2dc2892..28aa1d7f2 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "Ч" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "кОм" #define D_UNIT_KILOWATTHOUR "кВт" #define D_UNIT_LUX "лк" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index ea3f10ce6..0588b5175 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -536,7 +536,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index cf9d8bcf3..fc32479fc 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "Г" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "кОм" #define D_UNIT_KILOWATTHOUR "кВт" #define D_UNIT_LUX "лк" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 15708dded..f4a19e324 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -536,7 +536,7 @@ #define D_UNIT_HOUR "时" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "千欧" #define D_UNIT_KILOWATTHOUR "千瓦时" #define D_UNIT_LUX "勒克斯" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 75c682396..61fa90d4d 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "時" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "千歐" #define D_UNIT_KILOWATTHOUR "千瓦時" #define D_UNIT_LUX "勒克斯" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 81eb4e987..5b721af2a 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -281,7 +281,7 @@ #ifdef USE_I2C #define USE_SHT // Enable SHT1X sensor (+1k4 code) #define USE_HTU // Enable HTU21/SI7013/SI7020/SI7021 sensor (I2C address 0x40) (+1k5 code) - #define USE_BMP // Enable BMP085/BMP180/BMP280/BME280 sensor (I2C address 0x76 or 0x77) (+4k code) + #define USE_BMP // Enable BMP085/BMP180/BMP280/BME280 sensors (I2C addresses 0x76 and 0x77) (+4k4 code) // #define USE_BME680 // Enable support for BME680 sensor using Bosch BME680 library (+4k code) #define USE_BH1750 // Enable BH1750 sensor (I2C address 0x23 or 0x5C) (+0k5 code) // #define USE_VEML6070 // Enable VEML6070 sensor (I2C addresses 0x38 and 0x39) (+1k5 code) diff --git a/sonoff/settings.h b/sonoff/settings.h index 29aaf2121..8e0a22a2f 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -66,7 +66,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t timers_enable : 1; // bit 0 (v6.1.1b) uint32_t user_esp8285_enable : 1; // bit 1 (v6.1.1.14) uint32_t time_append_timezone : 1; // bit 2 (v6.2.1.2) - uint32_t spare03 : 1; + uint32_t gui_hostname_ip : 1; // bit 3 (v6.2.1.20) uint32_t spare04 : 1; uint32_t spare05 : 1; uint32_t spare06 : 1; diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 70e0e9a3d..ebc2ddb8a 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -60,6 +60,7 @@ typedef unsigned long power_t; // Power (Relay) type #define MQTT_TOKEN_PREFIX "%prefix%" // To be substituted by mqtt_prefix[x] #define MQTT_TOKEN_TOPIC "%topic%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic +#define MQTT_TOKEN_HOSTNAME "%hostname%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic #define MQTT_TOKEN_ID "%id%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic #define WIFI_HOSTNAME "%s-%04d" // Expands to - @@ -202,7 +203,7 @@ enum ButtonStates { PRESSED, NOT_PRESSED }; enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; -enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MAX_PARAM8}; +enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_MAX_SENSORS}; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 153e55fb7..2258ab240 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -186,6 +186,7 @@ byte reset_web_log_flag = 0; // Reset web console log byte devices_present = 0; // Max number of devices supported byte seriallog_level; // Current copy of Settings.seriallog_level byte syslog_level; // Current copy of Settings.syslog_level +byte mdns_delayed_start = 0; // mDNS delayed start boolean latest_uptime_flag = true; // Signal latest uptime boolean pwm_present = false; // Any PWM channel configured with SetOption15 0 boolean mdns_begun = false; // mDNS active @@ -278,6 +279,7 @@ void GetTopic_P(char *stopic, byte prefix, char *topic, const char* subtopic) } fulltopic.replace(F(MQTT_TOKEN_PREFIX), Settings.mqtt_prefix[prefix]); fulltopic.replace(F(MQTT_TOKEN_TOPIC), topic); + fulltopic.replace(F(MQTT_TOKEN_HOSTNAME), my_hostname); String token_id = WiFi.macAddress(); token_id.replace(":", ""); fulltopic.replace(F(MQTT_TOKEN_ID), token_id); @@ -2580,6 +2582,7 @@ void setup() } baudrate = Settings.baudrate * 1200; + mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; seriallog_level = Settings.seriallog_level; seriallog_timer = SERIALLOG_TIMER; #ifndef USE_EMULATION diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 2c70d6928..4a1b9ac5d 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06020112 +#define VERSION 0x06020114 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index 88545e211..67d55a8ab 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -715,7 +715,6 @@ boolean GetUsedInModule(byte val, uint8_t *arr) if (GPIO_RFRECV == val) { return true; } #endif - if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { offset = (GPIO_REL1_INV - GPIO_REL1); } @@ -1558,19 +1557,29 @@ void WifiCheck(uint8_t param) ota_state_flag = 3; } #endif // BE_MINIMAL + #ifdef USE_DISCOVERY if (!mdns_begun) { - mdns_begun = MDNS.begin(my_hostname); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MDNS "%s"), (mdns_begun) ? D_INITIALIZED : D_FAILED); - AddLog(LOG_LEVEL_INFO); + if (mdns_delayed_start) { + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_ATTEMPTING_CONNECTION)); + mdns_delayed_start--; + } else { + mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; + mdns_begun = MDNS.begin(my_hostname); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MDNS "%s"), (mdns_begun) ? D_INITIALIZED : D_FAILED); + AddLog(LOG_LEVEL_INFO); + } } #endif // USE_DISCOVERY + #ifdef USE_WEBSERVER if (Settings.webserver) { StartWebserver(Settings.webserver, WiFi.localIP()); #ifdef USE_DISCOVERY #ifdef WEBSERVER_ADVERTISE - MDNS.addService("http", "tcp", WEB_PORT); + if (mdns_begun) { + MDNS.addService("http", "tcp", WEB_PORT); + } #endif // WEBSERVER_ADVERTISE #endif // USE_DISCOVERY } else { @@ -1580,12 +1589,14 @@ void WifiCheck(uint8_t param) if (Settings.flag2.emulation) { UdpConnect(); } #endif // USE_EMULATION #endif // USE_WEBSERVER + #ifdef USE_KNX if (!knx_started && Settings.flag.knx_enabled) { KNXStart(); knx_started = true; } #endif // USE_KNX + } else { WifiState(0); #if defined(USE_WEBSERVER) && defined(USE_EMULATION) @@ -1646,38 +1657,6 @@ void EspRestart() ESP.restart(); } -#ifdef USE_DISCOVERY -/*********************************************************************************************\ - * mDNS -\*********************************************************************************************/ - -#ifdef MQTT_HOST_DISCOVERY -boolean MdnsDiscoverMqttServer() -{ - if (!mdns_begun) { - return false; - } - - int n = MDNS.queryService("mqtt", "tcp"); // Search for mqtt service - - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MDNS D_QUERY_DONE " %d"), n); - AddLog(LOG_LEVEL_INFO); - - if (n > 0) { - // Note: current strategy is to get the first MQTT service (even when many are found) - snprintf_P(Settings.mqtt_host, sizeof(Settings.mqtt_host), MDNS.IP(0).toString().c_str()); - Settings.mqtt_port = MDNS.port(0); - - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s, " D_IP_ADDRESS " %s, " D_PORT " %d"), - MDNS.hostname(0).c_str(), Settings.mqtt_host, Settings.mqtt_port); - AddLog(LOG_LEVEL_INFO); - } - - return n > 0; -} -#endif // MQTT_HOST_DISCOVERY -#endif // USE_DISCOVERY - /*********************************************************************************************\ * Basic I2C routines \*********************************************************************************************/ diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 3cb2b31cb..261510924 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -119,7 +119,7 @@ const char HTTP_HEAD_STYLE[] PROGMEM = #else "

{ha " D_MODULE "

" #endif - "

{h}

"; + "

{h}

{j}"; const char HTTP_SCRIPT_CONSOL[] PROGMEM = "var sn=0;" // Scroll position "var id=0;" // Get most of weblog initially @@ -453,6 +453,25 @@ void ShowPage(String &page, bool auth) page.replace(F("{a}"), String(Settings.web_refresh)); page.replace(F("{ha"), my_module.name); page.replace(F("{h}"), Settings.friendlyname[0]); + + String info = ""; + if (Settings.flag3.gui_hostname_ip) { + uint8_t more_ips = 0; + info += F("

"); info += my_hostname; + if (mdns_begun) { info += F(".local"); } + info += F(" ("); + if (static_cast(WiFi.localIP()) != 0) { + info += WiFi.localIP().toString(); + more_ips++; + } + if (static_cast(WiFi.softAPIP()) != 0) { + if (more_ips) { info += F(", "); } + info += WiFi.softAPIP().toString(); + } + info += F(")

"); + } + page.replace(F("{j}"), info); + if (HTTP_MANAGER == webserver_state) { if (WifiConfigCounter()) { page.replace(F(""), F("")); @@ -1241,6 +1260,7 @@ void HandleInformation() func += F("}1" D_AP); func += String(Settings.sta_active +1); func += F(" " D_SSID " (" D_RSSI ")}2"); func += Settings.sta_ssid[Settings.sta_active]; func += F(" ("); func += WifiGetRssiAsQuality(WiFi.RSSI()); func += F("%)"); func += F("}1" D_HOSTNAME "}2"); func += my_hostname; + if (mdns_begun) { func += F(".local"); } if (static_cast(WiFi.localIP()) != 0) { func += F("}1" D_IP_ADDRESS "}2"); func += WiFi.localIP().toString(); func += F("}1" D_GATEWAY "}2"); func += IPAddress(Settings.ip_address[1]).toString(); diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index bb1a86e13..ed24d31ed 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -197,6 +197,32 @@ void MqttLoop() /*********************************************************************************************/ +#ifdef USE_DISCOVERY +#ifdef MQTT_HOST_DISCOVERY +boolean MqttDiscoverServer() +{ + if (!mdns_begun) { return false; } + + int n = MDNS.queryService("mqtt", "tcp"); // Search for mqtt service + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MDNS D_QUERY_DONE " %d"), n); + AddLog(LOG_LEVEL_INFO); + + if (n > 0) { + // Note: current strategy is to get the first MQTT service (even when many are found) + snprintf_P(Settings.mqtt_host, sizeof(Settings.mqtt_host), MDNS.IP(0).toString().c_str()); + Settings.mqtt_port = MDNS.port(0); + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s, " D_IP_ADDRESS " %s, " D_PORT " %d"), + MDNS.hostname(0).c_str(), Settings.mqtt_host, Settings.mqtt_port); + AddLog(LOG_LEVEL_INFO); + } + + return n > 0; +} +#endif // MQTT_HOST_DISCOVERY +#endif // USE_DISCOVERY + int MqttLibraryType() { return (int)MQTT_LIBRARY_TYPE; @@ -468,9 +494,7 @@ void MqttReconnect() #ifndef USE_MQTT_TLS #ifdef USE_DISCOVERY #ifdef MQTT_HOST_DISCOVERY - if (!strlen(Settings.mqtt_host)) { - MdnsDiscoverMqttServer(); - } + if (!strlen(Settings.mqtt_host) && !MqttDiscoverServer()) { return; } #endif // MQTT_HOST_DISCOVERY #endif // USE_DISCOVERY #endif // USE_MQTT_TLS @@ -539,6 +563,13 @@ void MqttCheck() if (!MqttIsConnected()) { global_state.mqtt_down = 1; if (!mqtt_retry_counter) { +#ifndef USE_MQTT_TLS +#ifdef USE_DISCOVERY +#ifdef MQTT_HOST_DISCOVERY + if (!strlen(Settings.mqtt_host) && !mdns_begun) { return; } +#endif // MQTT_HOST_DISCOVERY +#endif // USE_DISCOVERY +#endif // USE_MQTT_TLS MqttReconnect(); } else { mqtt_retry_counter--; diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index f8eff5ddc..8bd5e529c 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -809,6 +809,11 @@ void HandleHueApi(String *path) * user part and allow every caller as with Web or WeMo. * * (c) Heiko Krupp, 2017 + * + * Hue URL + * http://sonoff/api/username/lights/1/state with post data {"on":true,"hue":56100,"sat":254,"bri":254,"alert":"none","transitiontime":40} + * is converted by webserver to + * http://sonoff/api/username/lights/1/state with arg plain={"on":true,"hue":56100,"sat":254,"bri":254,"alert":"none","transitiontime":40} */ uint8_t args = 0; diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index 8a50b8ae6..781b85f20 100755 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -27,8 +27,8 @@ * I2C Address: 0x76 or 0x77 \*********************************************************************************************/ -#define BMP_ADDR1 0x77 -#define BMP_ADDR2 0x76 +#define BMP_ADDR1 0x76 +#define BMP_ADDR2 0x77 #define BMP180_CHIPID 0x55 #define BMP280_CHIPID 0x58 @@ -37,18 +37,27 @@ #define BMP_REGISTER_CHIPID 0xD0 +#define BMP_MAX_SENSORS 2 + const char kBmpTypes[] PROGMEM = "BMP180|BMP280|BME280|BME680"; - -uint8_t bmp_address; uint8_t bmp_addresses[] = { BMP_ADDR1, BMP_ADDR2 }; -uint8_t bmp_type = 0; -uint8_t bmp_model = 0; -char bmp_name[7]; +uint8_t bmp_count = 0; -uint8_t bmp_valid = 0; -float bmp_temperature = 0.0; -float bmp_pressure = 0.0; -float bmp_humidity = 0.0; +struct BMPSTRUCT { + uint8_t bmp_address; // I2C bus address + char bmp_name[7]; // Sensor name - "BMPXXX" + uint8_t bmp_type = 0; + uint8_t bmp_model = 0; + + uint8_t bmp_valid = 0; +#ifdef USE_BME680 + uint8_t bme680_state = 0; + float bmp_gas_resistance = 0.0; +#endif // USE_BME680 + float bmp_temperature = 0.0; + float bmp_pressure = 0.0; + float bmp_humidity = 0.0; +} bmp_sensors[BMP_MAX_SENSORS]; /*********************************************************************************************\ * BMP085 and BME180 @@ -84,18 +93,18 @@ uint16_t cal_ac4; uint16_t cal_ac5; uint16_t cal_ac6; -boolean Bmp180Calibration() +boolean Bmp1802xCalibration(uint8_t bmp_idx) { - cal_ac1 = I2cRead16(bmp_address, BMP180_AC1); - cal_ac2 = I2cRead16(bmp_address, BMP180_AC2); - cal_ac3 = I2cRead16(bmp_address, BMP180_AC3); - cal_ac4 = I2cRead16(bmp_address, BMP180_AC4); - cal_ac5 = I2cRead16(bmp_address, BMP180_AC5); - cal_ac6 = I2cRead16(bmp_address, BMP180_AC6); - cal_b1 = I2cRead16(bmp_address, BMP180_VB1); - cal_b2 = I2cRead16(bmp_address, BMP180_VB2); - cal_mc = I2cRead16(bmp_address, BMP180_MC); - cal_md = I2cRead16(bmp_address, BMP180_MD); + cal_ac1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC1); + cal_ac2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC2); + cal_ac3 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC3); + cal_ac4 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC4); + cal_ac5 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC5); + cal_ac6 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC6); + cal_b1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB1); + cal_b2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB2); + cal_mc = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_MC); + cal_md = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_MD); // Check for Errors in calibration data. Value never is 0x0000 or 0xFFFF if (!cal_ac1 | !cal_ac2 | !cal_ac3 | !cal_ac4 | !cal_ac5 | !cal_ac6 | !cal_b1 | !cal_b2 | !cal_mc | !cal_md) { @@ -117,19 +126,20 @@ boolean Bmp180Calibration() return true; } -void Bmp180Read() +void Bmp1802xRead(uint8_t bmp_idx) { - I2cWrite8(bmp_address, BMP180_REG_CONTROL, BMP180_TEMPERATURE); + + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_CONTROL, BMP180_TEMPERATURE); delay(5); // 5ms conversion time - int ut = I2cRead16(bmp_address, BMP180_REG_RESULT); + int ut = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT); int32_t xt1 = (ut - (int32_t)cal_ac6) * ((int32_t)cal_ac5) >> 15; int32_t xt2 = ((int32_t)cal_mc << 11) / (xt1 + (int32_t)cal_md); int32_t bmp180_b5 = xt1 + xt2; - bmp_temperature = ((bmp180_b5 + 8) >> 4) / 10.0; + bmp_sensors[bmp_idx].bmp_temperature = ((bmp180_b5 + 8) >> 4) / 10.0; - I2cWrite8(bmp_address, BMP180_REG_CONTROL, BMP180_PRESSURE3); // Highest resolution + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_CONTROL, BMP180_PRESSURE3); // Highest resolution delay(2 + (4 << BMP180_OSS)); // 26ms conversion time at ultra high resolution - uint32_t up = I2cRead24(bmp_address, BMP180_REG_RESULT); + uint32_t up = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT); up >>= (8 - BMP180_OSS); int32_t b6 = bmp180_b5 - 4000; @@ -155,7 +165,7 @@ void Bmp180Read() x1 = (x1 * 3038) >> 16; x2 = (-7357 * p) >> 16; p += ((x1 + x2 + (int32_t)3791) >> 4); - bmp_pressure = (float)p / 100.0; // convert to mbar + bmp_sensors[bmp_idx].bmp_pressure = (float)p / 100.0; // convert to mbar } /*********************************************************************************************\ @@ -212,45 +222,45 @@ struct BME280CALIBDATA int8_t dig_H6; } Bme280CalibrationData; -boolean Bmx280Calibrate() +boolean Bmx2802xCalibrate(uint8_t bmp_idx) { // if (I2cRead8(bmp_address, BMP_REGISTER_CHIPID) != BME280_CHIPID) return false; - Bme280CalibrationData.dig_T1 = I2cRead16LE(bmp_address, BME280_REGISTER_DIG_T1); - Bme280CalibrationData.dig_T2 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_T2); - Bme280CalibrationData.dig_T3 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_T3); - Bme280CalibrationData.dig_P1 = I2cRead16LE(bmp_address, BME280_REGISTER_DIG_P1); - Bme280CalibrationData.dig_P2 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_P2); - Bme280CalibrationData.dig_P3 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_P3); - Bme280CalibrationData.dig_P4 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_P4); - Bme280CalibrationData.dig_P5 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_P5); - Bme280CalibrationData.dig_P6 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_P6); - Bme280CalibrationData.dig_P7 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_P7); - Bme280CalibrationData.dig_P8 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_P8); - Bme280CalibrationData.dig_P9 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_P9); - if (BME280_CHIPID == bmp_type) { // #1051 - Bme280CalibrationData.dig_H1 = I2cRead8(bmp_address, BME280_REGISTER_DIG_H1); - Bme280CalibrationData.dig_H2 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_H2); - Bme280CalibrationData.dig_H3 = I2cRead8(bmp_address, BME280_REGISTER_DIG_H3); - Bme280CalibrationData.dig_H4 = (I2cRead8(bmp_address, BME280_REGISTER_DIG_H4) << 4) | (I2cRead8(bmp_address, BME280_REGISTER_DIG_H4 + 1) & 0xF); - Bme280CalibrationData.dig_H5 = (I2cRead8(bmp_address, BME280_REGISTER_DIG_H5 + 1) << 4) | (I2cRead8(bmp_address, BME280_REGISTER_DIG_H5) >> 4); - Bme280CalibrationData.dig_H6 = (int8_t)I2cRead8(bmp_address, BME280_REGISTER_DIG_H6); + Bme280CalibrationData.dig_T1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T1); + Bme280CalibrationData.dig_T2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T2); + Bme280CalibrationData.dig_T3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T3); + Bme280CalibrationData.dig_P1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P1); + Bme280CalibrationData.dig_P2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P2); + Bme280CalibrationData.dig_P3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P3); + Bme280CalibrationData.dig_P4 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P4); + Bme280CalibrationData.dig_P5 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P5); + Bme280CalibrationData.dig_P6 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P6); + Bme280CalibrationData.dig_P7 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P7); + Bme280CalibrationData.dig_P8 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P8); + Bme280CalibrationData.dig_P9 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P9); + if (BME280_CHIPID == bmp_sensors[bmp_idx].bmp_type) { // #1051 + Bme280CalibrationData.dig_H1 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H1); + Bme280CalibrationData.dig_H2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H2); + Bme280CalibrationData.dig_H3 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H3); + Bme280CalibrationData.dig_H4 = (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H4) << 4) | (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H4 + 1) & 0xF); + Bme280CalibrationData.dig_H5 = (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H5 + 1) << 4) | (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H5) >> 4); + Bme280CalibrationData.dig_H6 = (int8_t)I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H6); - I2cWrite8(bmp_address, BME280_REGISTER_CONTROL, 0x00); // sleep mode since writes to config can be ignored in normal mode (Datasheet 5.4.5/6 page 27) + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0x00); // sleep mode since writes to config can be ignored in normal mode (Datasheet 5.4.5/6 page 27) // Set before CONTROL_meas (DS 5.4.3) - I2cWrite8(bmp_address, BME280_REGISTER_CONTROLHUMID, 0x01); // 1x oversampling - I2cWrite8(bmp_address, BME280_REGISTER_CONFIG, 0xA0); // 1sec standby between measurements (to limit self heating), IIR filter off - I2cWrite8(bmp_address, BME280_REGISTER_CONTROL, 0x27); // 1x oversampling, normal mode + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROLHUMID, 0x01); // 1x oversampling + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONFIG, 0xA0); // 1sec standby between measurements (to limit self heating), IIR filter off + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0x27); // 1x oversampling, normal mode } else { - I2cWrite8(bmp_address, BME280_REGISTER_CONTROL, 0xB7); // 16x oversampling, normal mode (Adafruit) + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0xB7); // 16x oversampling, normal mode (Adafruit) } return true; } -void Bme280Read(void) +void Bme2802xRead(uint8_t bmp_idx) { - int32_t adc_T = I2cRead24(bmp_address, BME280_REGISTER_TEMPDATA); + int32_t adc_T = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_TEMPDATA); adc_T >>= 4; int32_t vart1 = ((((adc_T >> 3) - ((int32_t)Bme280CalibrationData.dig_T1 << 1))) * ((int32_t)Bme280CalibrationData.dig_T2)) >> 11; @@ -258,9 +268,9 @@ void Bme280Read(void) ((int32_t)Bme280CalibrationData.dig_T3)) >> 14; int32_t t_fine = vart1 + vart2; float T = (t_fine * 5 + 128) >> 8; - bmp_temperature = T / 100.0; + bmp_sensors[bmp_idx].bmp_temperature = T / 100.0; - int32_t adc_P = I2cRead24(bmp_address, BME280_REGISTER_PRESSUREDATA); + int32_t adc_P = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_PRESSUREDATA); adc_P >>= 4; int64_t var1 = ((int64_t)t_fine) - 128000; @@ -277,11 +287,11 @@ void Bme280Read(void) var1 = (((int64_t)Bme280CalibrationData.dig_P9) * (p >> 13) * (p >> 13)) >> 25; var2 = (((int64_t)Bme280CalibrationData.dig_P8) * p) >> 19; p = ((p + var1 + var2) >> 8) + (((int64_t)Bme280CalibrationData.dig_P7) << 4); - bmp_pressure = (float)p / 25600.0; + bmp_sensors[bmp_idx].bmp_pressure = (float)p / 25600.0; - if (BMP280_CHIPID == bmp_type) { return; } + if (BMP280_CHIPID == bmp_sensors[bmp_idx].bmp_type) { return; } - int32_t adc_H = I2cRead16(bmp_address, BME280_REGISTER_HUMIDDATA); + int32_t adc_H = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_HUMIDDATA); int32_t v_x1_u32r = (t_fine - ((int32_t)76800)); v_x1_u32r = (((((adc_H << 14) - (((int32_t)Bme280CalibrationData.dig_H4) << 20) - @@ -294,7 +304,7 @@ void Bme280Read(void) v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; float h = (v_x1_u32r >> 12); - bmp_humidity = h / 1024.0; + bmp_sensors[bmp_idx].bmp_humidity = h / 1024.0; } #ifdef USE_BME680 @@ -306,17 +316,14 @@ void Bme280Read(void) struct bme680_dev gas_sensor; -float bmp_gas_resistance = 0.0; -uint8_t bme680_state = 0; - static void BmeDelayMs(uint32_t ms) { delay(ms); } -boolean Bme680Init() +boolean Bme6802xInit(uint8_t bmp_idx) { - gas_sensor.dev_id = bmp_address; + gas_sensor.dev_id = bmp_sensors[bmp_idx].bmp_address; gas_sensor.intf = BME680_I2C_INTF; gas_sensor.read = &I2cReadBuffer; gas_sensor.write = &I2cWriteBuffer; @@ -353,17 +360,17 @@ boolean Bme680Init() rslt = bme680_set_sensor_settings(set_required_settings,&gas_sensor); if (rslt != BME680_OK) { return false; } - bme680_state = 0; + bmp_sensors[bmp_idx].bme680_state = 0; return true; } -void Bme680Read() +void Bme6802xRead(uint8_t bmp_idx) { int8_t rslt = BME680_OK; - if (BME680_CHIPID == bmp_type) { - if (0 == bme680_state) { + if (BME680_CHIPID == bmp_sensors[bmp_idx].bmp_type) { + if (0 == bmp_sensors[bmp_idx].bme680_state) { /* Trigger the next measurement if you would like to read data out continuously */ rslt = bme680_set_sensor_mode(&gas_sensor); if (rslt != BME680_OK) { return; } @@ -374,22 +381,22 @@ void Bme680Read() // bme680_get_profile_dur(&meas_period, &gas_sensor); // delay(meas_period); /* Delay till the measurement is ready */ // 183 mSec - we'll wait a second - bme680_state = 1; + bmp_sensors[bmp_idx].bme680_state = 1; } else { - bme680_state = 0; + bmp_sensors[bmp_idx].bme680_state = 0; struct bme680_field_data data; rslt = bme680_get_sensor_data(&data, &gas_sensor); if (rslt != BME680_OK) { return; } - bmp_temperature = data.temperature / 100.0; - bmp_humidity = data.humidity / 1000.0; - bmp_pressure = data.pressure / 100.0; + bmp_sensors[bmp_idx].bmp_temperature = data.temperature / 100.0; + bmp_sensors[bmp_idx].bmp_humidity = data.humidity / 1000.0; + bmp_sensors[bmp_idx].bmp_pressure = data.pressure / 100.0; /* Avoid using measurements from an unstable heating setup */ if (data.status & BME680_GASM_VALID_MSK) { - bmp_gas_resistance = data.gas_resistance / 1000.0; + bmp_sensors[bmp_idx].bmp_gas_resistance = data.gas_resistance / 1000.0; } else { - bmp_gas_resistance = 0; + bmp_sensors[bmp_idx].bmp_gas_resistance = 0; } } } @@ -402,65 +409,66 @@ void Bme680Read() void BmpDetect() { - if (bmp_type) { return; } + if (bmp_count) return; - for (byte i = 0; i < sizeof(bmp_addresses); i++) { - bmp_address = bmp_addresses[i]; - bmp_type = I2cRead8(bmp_address, BMP_REGISTER_CHIPID); + for (byte i = 0; i < BMP_MAX_SENSORS; i++) { + uint8_t bmp_type = I2cRead8(bmp_addresses[i], BMP_REGISTER_CHIPID); if (bmp_type) { - break; - } - } - if (bmp_type) { - bmp_model = 0; - boolean success = false; - switch (bmp_type) { - case BMP180_CHIPID: - success = Bmp180Calibration(); - break; - case BME280_CHIPID: - bmp_model++; // 2 - case BMP280_CHIPID: - bmp_model++; // 1 - success = Bmx280Calibrate(); - break; -#ifdef USE_BME680 - case BME680_CHIPID: - bmp_model = 3; // 3 - success = Bme680Init(); - break; -#endif // USE_BME680 - } - if (success) { - GetTextIndexed(bmp_name, sizeof(bmp_name), bmp_model, kBmpTypes); - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, bmp_name, bmp_address); - AddLog(LOG_LEVEL_DEBUG); - } - else { - bmp_type = 0; + bmp_sensors[bmp_count].bmp_address = bmp_addresses[i]; + bmp_sensors[bmp_count].bmp_type = bmp_type; + bmp_sensors[bmp_count].bmp_model = 0; + + boolean success = false; + switch (bmp_type) { + case BMP180_CHIPID: + success = Bmp1802xCalibration(bmp_count); + break; + case BME280_CHIPID: + bmp_sensors[bmp_count].bmp_model++; // 2 + case BMP280_CHIPID: + bmp_sensors[bmp_count].bmp_model++; // 1 + success = Bmx2802xCalibrate(bmp_count); + break; + #ifdef USE_BME680 + case BME680_CHIPID: + bmp_sensors[bmp_count].bmp_model = 3; // 3 + success = Bme6802xInit(bmp_count); + break; + #endif // USE_BME680 + } + if (success) { + GetTextIndexed(bmp_sensors[bmp_count].bmp_name, sizeof(bmp_sensors[bmp_count].bmp_name), bmp_sensors[bmp_count].bmp_model, kBmpTypes); + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, bmp_sensors[bmp_count].bmp_name, bmp_sensors[bmp_count].bmp_address); + AddLog(LOG_LEVEL_DEBUG); + bmp_count++; + } } } } void BmpRead() { - switch (bmp_type) { - case BMP180_CHIPID: - Bmp180Read(); - break; - case BMP280_CHIPID: - case BME280_CHIPID: - Bme280Read(); - break; -#ifdef USE_BME680 - case BME680_CHIPID: - Bme680Read(); - break; -#endif // USE_BME680 + for (byte bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { + switch (bmp_sensors[bmp_idx].bmp_type) { + case BMP180_CHIPID: + Bmp1802xRead(bmp_idx); + break; + case BMP280_CHIPID: + case BME280_CHIPID: + Bme2802xRead(bmp_idx); + break; + #ifdef USE_BME680 + case BME680_CHIPID: + Bme6802xRead(bmp_idx); + break; + #endif // USE_BME680 + } + if (bmp_sensors[bmp_idx].bmp_temperature != 0.0) { + bmp_sensors[bmp_idx].bmp_temperature = ConvertTemp(bmp_sensors[bmp_idx].bmp_temperature); + } } - if (bmp_temperature != 0.0) { bmp_temperature = ConvertTemp(bmp_temperature); } - SetGlobalValues(bmp_temperature, bmp_humidity); + SetGlobalValues(bmp_sensors[0].bmp_temperature, bmp_sensors[0].bmp_humidity); } void BmpEverySecond() @@ -477,72 +485,91 @@ void BmpEverySecond() void BmpShow(boolean json) { - if (bmp_type) { - float bmp_sealevel = 0.0; - char temperature[10]; - char pressure[10]; - char sea_pressure[10]; - char humidity[10]; + for (byte bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { + if (bmp_sensors[bmp_idx].bmp_type) { + float bmp_sealevel = 0.0; + char temperature[10]; + char pressure[10]; + char sea_pressure[10]; + char humidity[10]; + char name[10]; - if (bmp_pressure != 0.0) { - bmp_sealevel = (bmp_pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; - } - - dtostrfd(bmp_temperature, Settings.flag2.temperature_resolution, temperature); - dtostrfd(bmp_pressure, Settings.flag2.pressure_resolution, pressure); - dtostrfd(bmp_sealevel, Settings.flag2.pressure_resolution, sea_pressure); - dtostrfd(bmp_humidity, Settings.flag2.humidity_resolution, humidity); -#ifdef USE_BME680 - char gas_resistance[10]; - dtostrfd(bmp_gas_resistance, 2, gas_resistance); -#endif // USE_BME680 - - if (json) { - char json_humidity[40]; - snprintf_P(json_humidity, sizeof(json_humidity), PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); - char json_sealevel[40]; - snprintf_P(json_sealevel, sizeof(json_sealevel), PSTR(",\"" D_JSON_PRESSUREATSEALEVEL "\":%s"), sea_pressure); -#ifdef USE_BME680 - char json_gas[40]; - snprintf_P(json_gas, sizeof(json_gas), PSTR(",\"" D_JSON_GAS "\":%s"), gas_resistance); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s%s}"), - mqtt_data, bmp_name, temperature, (bmp_model >= 2) ? json_humidity : "", pressure, (Settings.altitude != 0) ? json_sealevel : "", (bmp_model >= 3) ? json_gas : ""); -#else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s}"), - mqtt_data, bmp_name, temperature, (bmp_model >= 2) ? json_humidity : "", pressure, (Settings.altitude != 0) ? json_sealevel : ""); -#endif // USE_BME680 -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumPressureSensor(temperature, humidity, pressure); -#ifdef USE_BME680 - if (bmp_model >= 3) { DomoticzSensor(DZ_AIRQUALITY, (uint32_t)bmp_gas_resistance); } -#endif // USE_BME680 + if (bmp_sensors[bmp_idx].bmp_pressure != 0.0) { + bmp_sealevel = (bmp_sensors[bmp_idx].bmp_pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; } + + snprintf(name, sizeof(name), bmp_sensors[bmp_idx].bmp_name); + if (bmp_count > 1) { + snprintf_P(name, sizeof(name), PSTR("%s-%02X"), name, bmp_sensors[bmp_idx].bmp_address); // BMXXXX-XX + } + + dtostrfd(bmp_sensors[bmp_idx].bmp_temperature, Settings.flag2.temperature_resolution, temperature); + dtostrfd(bmp_sensors[bmp_idx].bmp_pressure, Settings.flag2.pressure_resolution, pressure); + dtostrfd(bmp_sealevel, Settings.flag2.pressure_resolution, sea_pressure); + dtostrfd(bmp_sensors[bmp_idx].bmp_humidity, Settings.flag2.humidity_resolution, humidity); +#ifdef USE_BME680 + char gas_resistance[10]; + dtostrfd(bmp_sensors[bmp_idx].bmp_gas_resistance, 2, gas_resistance); +#endif // USE_BME680 + + if (json) { + char json_humidity[40]; + snprintf_P(json_humidity, sizeof(json_humidity), PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); + char json_sealevel[40]; + snprintf_P(json_sealevel, sizeof(json_sealevel), PSTR(",\"" D_JSON_PRESSUREATSEALEVEL "\":%s"), sea_pressure); +#ifdef USE_BME680 + char json_gas[40]; + snprintf_P(json_gas, sizeof(json_gas), PSTR(",\"" D_JSON_GAS "\":%s"), gas_resistance); + + snprintf_P(mqtt_data, + sizeof(mqtt_data), + PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s%s}"), + mqtt_data, + name, + temperature, + (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", + pressure, + (Settings.altitude != 0) ? json_sealevel : "", + (bmp_sensors[bmp_idx].bmp_model >= 3) ? json_gas : "" + ); +#else + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s}"), + mqtt_data, name, temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", pressure, (Settings.altitude != 0) ? json_sealevel : ""); +#endif // USE_BME680 + +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == bmp_idx)) { // We want the same first sensor to report to Domoticz in case a read is missed + DomoticzTempHumPressureSensor(temperature, humidity, pressure); +#ifdef USE_BME680 + if (bmp_sensors[bmp_idx].bmp_model >= 3) { DomoticzSensor(DZ_AIRQUALITY, (uint32_t)bmp_sensors[bmp_idx].bmp_gas_resistance); } +#endif // USE_BME680 + } #endif // USE_DOMOTICZ #ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, bmp_temperature); - KnxSensor(KNX_HUMIDITY, bmp_humidity); - } + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, bmp_sensors[bmp_idx].bmp_temperature); + KnxSensor(KNX_HUMIDITY, bmp_sensors[bmp_idx].bmp_humidity); + } #endif // USE_KNX #ifdef USE_WEBSERVER - } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, bmp_name, temperature, TempUnit()); - if (bmp_model >= 2) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, bmp_name, humidity); - } - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_PRESSURE, mqtt_data, bmp_name, pressure); - if (Settings.altitude != 0) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SEAPRESSURE, mqtt_data, bmp_name, sea_pressure); - } + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, name, temperature, TempUnit()); + if (bmp_sensors[bmp_idx].bmp_model >= 2) { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, name, humidity); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_PRESSURE, mqtt_data, name, pressure); + if (Settings.altitude != 0) { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SEAPRESSURE, mqtt_data, name, sea_pressure); + } #ifdef USE_BME680 - if (bmp_model >= 3) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{s}%s " D_GAS "{m}%s " D_UNIT_KILOOHM "{e}"), mqtt_data, bmp_name, gas_resistance); - } + if (bmp_sensors[bmp_idx].bmp_model >= 3) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{s}%s " D_GAS "{m}%s " D_UNIT_KILOOHM "{e}"), mqtt_data, name, gas_resistance); + } #endif // USE_BME680 #endif // USE_WEBSERVER + } } } } diff --git a/tools/decode-config.py b/tools/decode-config.py index 1eb991d11..8e160f751 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.0.0000' +VER = '2.0.0001' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -201,7 +201,7 @@ DEFAULTS = { 'jsonsort': True, 'jsonrawvalues':False, 'jsonrawkeys': False, - 'jsonhidepw': True, + 'jsonhidepw': False, }, } args = {} @@ -250,21 +250,27 @@ Settings dictionary describes the config file fields definition: negative shift the result left bits datadef - Define the field interpretation different from simple - standard types (like char, byte, int) e. g. lists or bit fields - Can be None, a single integer, a list or a dictionary - None: - None must be given if the field contains a simple value - desrcibed by the prefix - n: - Same as [n] below - [n]: - Defines a one-dimensional array of size - [n, n <,n...>] - Defines a multi-dimensional array + Data definition, is either a array definition or a + tuple containing an array definition and min/max values + Format: arraydef|(arraydef, min, max) + arraydef: + None: + None must be given if the field contains a + simple value desrcibed by the prefix + n: + [n]: + Defines a one-dimensional array of size + [n, m <,o...>] + Defines a multi-dimensional array + min: + defines a minimum valid value or None if all values + for this format is allowed. + max: + defines a maximum valid value or None if all values + for this format is allowed. converter (optional) - Conversion methode(s): ()|'xxx'|func + Conversion methode(s): 'xxx'|func or ('xxx'|func, 'xxx'|func) Read conversion is used if args.jsonrawvalues is False Write conversion is used if jsonrawvalues from restore json file is False or args.jsonrawvalues is False. @@ -845,7 +851,19 @@ Setting_6_2_1_19.update({ 'weight_max': ('= cfg[0]: + template = cfg + size = template[1] + setting = template[2] + break except: - return None,None,None,None - - # search setting definition - template = None - setting = None - size = None - for cfg in Settings: - if version >= cfg[0]: - template = cfg - size = template[1] - setting = template[2] - break + pass return version, template, size, setting @@ -1652,6 +1671,9 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): result = None + if fieldname == 'raw' and not args.jsonrawkeys: + return result + # get field definition _format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) @@ -1662,7 +1684,7 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): for i in range(0, datadef[0]): subfielddef = GetSubfieldDef(fielddef) length = GetFieldLength(subfielddef) - if length != 0 and (fieldname != 'raw' or args.jsonrawkeys): + if length != 0: result.append(GetField(dobj, fieldname, subfielddef, raw=raw, addroffset=addroffset+offset)) offset += length @@ -1722,6 +1744,9 @@ def SetField(dobj, fieldname, fielddef, restore, raw=False, addroffset=0, filena _format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) fieldname = str(fieldname) + if fieldname == 'raw' and not args.jsonrawkeys: + return dobj + # do not write readonly values if isinstance(convert, (list,tuple)) and len(convert)>1 and convert[1]==None: if args.debug: