From 6d58580446b5456dfaa682420963ed7978d0e149 Mon Sep 17 00:00:00 2001
From: Theo Arends <11044339+arendst@users.noreply.github.com>
Date: Tue, 30 Oct 2018 17:29:01 +0100
Subject: [PATCH] Updates for release 6.3.0

Updates for release 6.3.0
---
 RELEASENOTES.md               |  22 +-
 sonoff/_changelog.ino         |  18 +-
 sonoff/i18n.h                 |   1 +
 sonoff/my_user_config.h       |   6 +-
 sonoff/settings.h             |   5 +-
 sonoff/sonoff.h               |   3 +-
 sonoff/sonoff.ino             |   1 +
 sonoff/support.ino            |   8 +-
 sonoff/xdrv_01_webserver.ino  |  22 +-
 sonoff/xdrv_03_energy.ino     |   5 +-
 sonoff/xdrv_16_tuyadimmer.ino |  44 ++-
 sonoff/xdrv_17_rcswitch.ino   |   2 +-
 sonoff/xsns_09_bmp.ino        | 541 ++++++++++++++++++----------------
 13 files changed, 391 insertions(+), 287 deletions(-)

diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 99afc7ea7..1688baa35 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -34,8 +34,8 @@ See [Tasmota ESP/Arduino library version related issues](https://github.com/aren
 
 | Feature or Sensor              | minimal | basic | classic | sonoff | knx  | sensors | Remarks
 |--------------------------------|---------|-------|---------|--------|------|---------|--------
-| ESP/Arduino lib v2.3.0         | 344k    | xxxk  | 485k    | 491k   | 510k | 516k    |
-| ESP/Arduino lib v2.4.2         | 363k    | xxxk  | 499k    | 509k   | 526k | 532k    | No sleep
+| ESP/Arduino lib v2.3.0         | 343k    | 425k  | 484k    | 490k   | 508k | 517k    |
+| ESP/Arduino lib v2.4.2         | 372k    | 451k  | 497k    | 517k   | 533k | 541k    | No sleep
 |                                |   |   |   |   |   |   |
 | MY_LANGUAGE en-GB              | x | x | x | x | x | x |
 | MQTT_LIBRARY_TYPE PUBSUBCLIENT | x | x | x | x | x | x |
@@ -173,10 +173,11 @@ Version 6.3.0 20181030
  * Add command SerialSend5 to send raw serial data like "A5074100545293"
  * Add command WebRefresh 1000..10000 to control web page refresh in milliseconds. Default is 2345
  * Add command WeightRes 0..3 to control display of decimals for kilogram
- * Add command SetOption52 to control display of optional time offset from UTC in JSON messages (#3629, #3711)
  * Add command RGBWWTable to support color calibration (#3933)
  * Add command Reset 4 (reset to defaults but keep wifi params) and Reset 5 (as reset 4 and also erase flash) (#4061)
  * Add command SetOption35 0..255 (seconds) to delay mDNS initialization to control possible Wifi connect problems
+ * Add command SetOption52 0/1 to control display of optional time offset from UTC in JSON messages (#3629, #3711)
+ * Add command SetOption53 0/1 to toggle gui display of Hostname and IP address (#1006, #2091)
  * Add authentication to HTTP web pages
  * Add decimals as input to commands PowerSet, VoltageSet and CurrentSet
  * Add tools/decode-config.py by Norbert Richter to decode configuration data. See file for information
@@ -185,18 +186,21 @@ Version 6.3.0 20181030
  * Add auto reload of main web page to some web restarts
  * Add TasmotaModbus library as very basic modbus wrapper for TasmotaSerial
  * Add more API callbacks and document API.md
+ * Add Apparent Power and Reactive Power to Energy Monitoring devices (#251)
+ * Add token %hostname% to command FullTopic (#3018)
  * Add Wifi channel number to state message (#3664)
  * Add user configurable GPIO02 and GPIO03 on H801 devices (#3692)
- * Add network information to display start screen (#3704)
  * Add toggle function RGBW lights (#3695, #3697)
+ * Add network information to display start screen (#3704)
  * Add sleep to Nova Fitness SDS01X sensor (#2841, #3724, #3749)
  * Add Analog input AD0 enabled to sonoff-sensors.bin (#3756, #3757)
- * Add userid/password option to decode-status.py (#3796)
  * Add power value below 5W to Sonoff Pow R2 and S31 (#3745)
- * Add force_update to Home Assistant discovery (#3873)
- * Add delay after restart before processing rule sensor data (#3811)
- * Add rule triggers SWITCH1#BOOT and POWER1#BOOT (#3904, #3910)
- * Add Apparent Power and Reactive Power to Energy Monitoring devices (#251)
  * Add RF Receiver control to module MagicHome to be used on Arilux LC10 (#3792)
+ * Add userid/password option to decode-status.py (#3796)
+ * Add delay after restart before processing rule sensor data (#3811)
+ * Add force_update to Home Assistant discovery (#3873)
+ * Add rule triggers SWITCH1#BOOT and POWER1#BOOT (#3904, #3910)
  * Add Hebrew language file (#3960)
+ * Add TotalStartTime to Energy JSON message (#3971)
  * Add whitespace removal from RfRaw and SerialSend5 (#4020)
+ * Add support for two BMP/BME sensors (#4195)
diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino
index 0861b29a0..91bbd83a8 100644
--- a/sonoff/_changelog.ino
+++ b/sonoff/_changelog.ino
@@ -55,10 +55,11 @@
  * Add command SerialSend5 to send raw serial data like "A5074100545293"
  * Add command WebRefresh 1000..10000 to control web page refresh in milliseconds. Default is 2345
  * Add command WeightRes 0..3 to control display of decimals for kilogram
- * Add command SetOption52 to control display of optional time offset from UTC in JSON messages (#3629, #3711)
  * Add command RGBWWTable to support color calibration (#3933)
  * Add command Reset 4 (reset to defaults but keep wifi params) and Reset 5 (as reset 4 and also erase flash) (#4061)
  * Add command SetOption35 0..255 (seconds) to delay mDNS initialization to control possible Wifi connect problems
+ * Add command SetOption52 0/1 to control display of optional time offset from UTC in JSON messages (#3629, #3711)
+ * Add command SetOption53 0/1 to toggle gui display of Hostname and IP address (#1006, #2091)
  * Add authentication to HTTP web pages
  * Add decimals as input to commands PowerSet, VoltageSet and CurrentSet
  * Add tools/decode-config.py by Norbert Richter to decode configuration data. See file for information
@@ -67,21 +68,24 @@
  * Add auto reload of main web page to some web restarts
  * Add TasmotaModbus library as very basic modbus wrapper for TasmotaSerial
  * Add more API callbacks and document API.md
+ * Add Apparent Power and Reactive Power to Energy Monitoring devices (#251)
+ * Add token %hostname% to command FullTopic (#3018)
  * Add Wifi channel number to state message (#3664)
  * Add user configurable GPIO02 and GPIO03 on H801 devices (#3692)
- * Add network information to display start screen (#3704)
  * Add toggle function RGBW lights (#3695, #3697)
+ * Add network information to display start screen (#3704)
  * Add sleep to Nova Fitness SDS01X sensor (#2841, #3724, #3749)
  * Add Analog input AD0 enabled to sonoff-sensors.bin (#3756, #3757)
- * Add userid/password option to decode-status.py (#3796)
  * Add power value below 5W to Sonoff Pow R2 and S31 (#3745)
- * Add force_update to Home Assistant discovery (#3873)
- * Add delay after restart before processing rule sensor data (#3811)
- * Add rule triggers SWITCH1#BOOT and POWER1#BOOT (#3904, #3910)
- * Add Apparent Power and Reactive Power to Energy Monitoring devices (#251)
  * Add RF Receiver control to module MagicHome to be used on Arilux LC10 (#3792)
+ * Add userid/password option to decode-status.py (#3796)
+ * Add delay after restart before processing rule sensor data (#3811)
+ * Add force_update to Home Assistant discovery (#3873)
+ * Add rule triggers SWITCH1#BOOT and POWER1#BOOT (#3904, #3910)
  * Add Hebrew language file (#3960)
+ * Add TotalStartTime to Energy JSON message (#3971)
  * Add whitespace removal from RfRaw and SerialSend5 (#4020)
+ * Add support for two BMP/BME sensors (#4195)
  *
  * 6.2.1 20180905
  * Fix possible ambiguity on command parameters if StateText contains numbers only (#3656)
diff --git a/sonoff/i18n.h b/sonoff/i18n.h
index 62226f91f..3067271e9 100644
--- a/sonoff/i18n.h
+++ b/sonoff/i18n.h
@@ -127,6 +127,7 @@
 #define D_JSON_TIME "Time"
 #define D_JSON_TODAY "Today"
 #define D_JSON_TOTAL "Total"
+#define D_JSON_TOTAL_START_TIME "TotalStartTime"
 #define D_JSON_TVOC "TVOC"
 #define D_JSON_TYPE "Type"
 #define D_JSON_UPTIME "Uptime"
diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h
index 82e32027e..458279fde 100644
--- a/sonoff/my_user_config.h
+++ b/sonoff/my_user_config.h
@@ -281,8 +281,8 @@
 #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_BME680                           // Enable support for BME680 sensor using Bosch BME680 library (+4k code)
+  #define USE_BMP                                // Enable BMP085/BMP180/BMP280/BME280 sensors (I2C addresses 0x76 and 0x77) (+4k1 code)
+//    #define USE_BME680                           // Enable support for BME680 sensors using Bosch BME680 library (+4k4 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)
     #define USE_VEML6070_RSET    270000          // VEML6070, Rset in Ohm used on PCB board, default 270K = 270000ohm, range for this sensor: 220K ... 1Meg
@@ -397,7 +397,7 @@
 \*********************************************************************************************/
 
 //#define USE_CLASSIC                              // Create sonoff-classic with initial configuration tools WPS, SmartConfig and WifiManager
-//#define USE_BASIC                                // Create sonoff-basic without sensors
+//#define USE_BASIC                                // Create sonoff-basic with no sensors
 //#define USE_SENSORS                              // Create sonoff-sensors with useful sensors enabled
 //#define USE_KNX_NO_EMULATION                     // Create sonoff-knx with KNX but without Emulation
 //#define USE_DISPLAYS                             // Create sonoff-display with display drivers enabled
diff --git a/sonoff/settings.h b/sonoff/settings.h
index 29aaf2121..4d1d61cd4 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;
@@ -322,8 +322,9 @@ struct SYSCFG {
   uint16_t      mcp230xx_int_timer;        // 718
   uint8_t       rgbwwTable[5];             // 71A
 
-  byte          free_71F[153];             // 71F
+  byte          free_71F[149];             // 71F
 
+  uint32_t      energy_kWhtotal_time;      // 7B4
   unsigned long weight_item;               // 7B8 Weight of one item in gram * 10
 
   byte          free_7BC[2];               // 7BC
diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h
index 15d003cd1..9bcbbb731 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 <MQTT_TOPIC>-<last 4 decimal chars of MAC address>
@@ -180,7 +181,7 @@ enum WeekInMonthOptions {Last, First, Second, Third, Fourth};
 enum DayOfTheWeekOptions {Sun=1, Mon, Tue, Wed, Thu, Fri, Sat};
 enum MonthNamesOptions {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};
 enum HemisphereOptions {North, South};
-enum GetDateAndTimeOptions { DT_LOCAL, DT_UTC, DT_RESTART };
+enum GetDateAndTimeOptions { DT_LOCAL, DT_UTC, DT_RESTART, DT_ENERGY };
 
 enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL};
 
diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino
index 5eadb50a8..2258ab240 100755
--- a/sonoff/sonoff.ino
+++ b/sonoff/sonoff.ino
@@ -279,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);
diff --git a/sonoff/support.ino b/sonoff/support.ino
index 67d55a8ab..9e1d82448 100644
--- a/sonoff/support.ino
+++ b/sonoff/support.ino
@@ -1946,6 +1946,10 @@ String GetDateAndTime(byte time_type)
   TIME_T tmpTime;
 
   switch (time_type) {
+    case DT_ENERGY:
+      BreakTime(Settings.energy_kWhtotal_time, tmpTime);
+      tmpTime.year += 1970;
+      break;
     case DT_UTC:
       BreakTime(utc_time, tmpTime);
       tmpTime.year += 1970;
@@ -1964,7 +1968,8 @@ String GetDateAndTime(byte time_type)
   snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"),
     tmpTime.year, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second);
 
-  if (Settings.flag3.time_append_timezone && (time_type == DT_LOCAL)) {
+  if (Settings.flag3.time_append_timezone && (DT_LOCAL == time_type)) {
+//  if (Settings.flag3.time_append_timezone && ((DT_LOCAL == time_type) || (DT_ENERGY == time_type))) {
     snprintf_P(dt, sizeof(dt), PSTR("%s%+03d:%02d"), dt, time_timezone / 10, abs((time_timezone % 10) * 6));  // if timezone = +2:30 then time_timezone = 25
   }
 
@@ -2225,6 +2230,7 @@ void RtcSecond()
     }
     local_time += time_offset;
     time_timezone = time_offset / 360;  // (SECS_PER_HOUR / 10) fails as it is defined as UL
+    if (!Settings.energy_kWhtotal_time) { Settings.energy_kWhtotal_time = local_time; }
   }
   BreakTime(local_time, RtcTime);
   if (!RtcTime.hour && !RtcTime.minute && !RtcTime.second && RtcTime.valid) {
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
   "<h3>{ha " D_MODULE "</h3>"
 #endif
-  "<h2>{h}</h2></div>";
+  "<h2>{h}</h2>{j}</div>";
 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("<h3>"); info += my_hostname;
+    if (mdns_begun) { info += F(".local"); }
+    info += F(" (");
+    if (static_cast<uint32_t>(WiFi.localIP()) != 0) {
+      info += WiFi.localIP().toString();
+      more_ips++;
+    }
+    if (static_cast<uint32_t>(WiFi.softAPIP()) != 0) {
+      if (more_ips) { info += F(", "); }
+      info += WiFi.softAPIP().toString();
+    }
+    info += F(")</h3>");
+  }
+  page.replace(F("{j}"), info);
+
   if (HTTP_MANAGER == webserver_state) {
     if (WifiConfigCounter()) {
       page.replace(F("<body>"), F("<body onload='u()'>"));
@@ -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<uint32_t>(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_03_energy.ino b/sonoff/xdrv_03_energy.ino
index 341fc71b5..717ff234c 100644
--- a/sonoff/xdrv_03_energy.ino
+++ b/sonoff/xdrv_03_energy.ino
@@ -393,6 +393,7 @@ boolean EnergyCommand()
         RtcSettings.energy_kWhtotal = lnum *100;
         Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal;
         energy_total = (float)(RtcSettings.energy_kWhtotal + energy_kWhtoday) / 100000;
+        if (!energy_total) { Settings.energy_kWhtotal_time = LocalTime(); }
         break;
       }
     }
@@ -612,8 +613,8 @@ void EnergyShow(boolean json)
   }
 
   if (json) {
-    snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s%s,\"" D_JSON_POWERUSAGE "\":%s"),
-      mqtt_data, energy_total_chr, energy_yesterday_chr, energy_daily_chr, (show_energy_period) ? speriod : "", active_power_chr);
+    snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s%s,\"" D_JSON_POWERUSAGE "\":%s"),
+      mqtt_data, GetDateAndTime(DT_ENERGY).c_str(), energy_total_chr, energy_yesterday_chr, energy_daily_chr, (show_energy_period) ? speriod : "", active_power_chr);
     if (!energy_type_dc) {
       snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s%s"),
         mqtt_data, apparent_power_chr, reactive_power_chr, power_factor_chr, (!isnan(energy_frequency)) ? sfrequency : "");
diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino
index eb700c322..bfc4fc903 100644
--- a/sonoff/xdrv_16_tuyadimmer.ino
+++ b/sonoff/xdrv_16_tuyadimmer.ino
@@ -33,6 +33,7 @@ boolean tuya_ignore_dim = false;            // Flag to skip serial send to preve
 uint8_t tuya_cmd_status = 0;                // Current status of serial-read
 uint8_t tuya_cmd_checksum = 0;              // Checksum of tuya command
 uint8_t tuya_data_len = 0;                  // Data lenght of command
+bool tuya_wifi_state = false;
 
 char tuya_buffer[TUYA_BUFFER_SIZE];         // Serial receive buffer
 int tuya_byte_counter = 0;                  // Index in serial receive buffer
@@ -142,12 +143,15 @@ void TuyaPacketProcess()
       ExecuteCommand(scmnd, SRC_SWITCH);
     }
   }
-  else if (tuya_byte_counter == 8 && tuya_buffer[3] == 5 && tuya_buffer[5] == 1 && tuya_buffer[7] == 5 ) {  // reset WiFi settings packet - to do: reset red MCU LED after WiFi is up
+  else if (tuya_byte_counter == 8 && tuya_buffer[3] == 5 && tuya_buffer[5] == 1 && tuya_buffer[7] == 5 ) {  // reset WiFi settings packet
 
     AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: WiFi Reset Rcvd"));
+    TuyaResetWifi();
+  }
+  else if (tuya_byte_counter == 7 && tuya_buffer[3] == 3 && tuya_buffer[6] == 2) {  // WiFi LED has been sucessfully reset.
 
-    snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " 2");
-    ExecuteCommand(scmnd, SRC_BUTTON);
+    AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: WiFi LED reset ACK"));
+    tuya_wifi_state = true;
   }
 }
 
@@ -221,6 +225,21 @@ boolean TuyaModuleSelected()
   return true;
 }
 
+void TuyaResetWifiLed(){
+    snprintf_P(log_data, sizeof(log_data), "TYA: Reset WiFi LED");
+    AddLog(LOG_LEVEL_DEBUG);
+
+    TuyaSerial->write((uint8_t)0x55); // header 55AA
+    TuyaSerial->write((uint8_t)0xAA);
+    TuyaSerial->write((uint8_t)0x00); // version 00
+    TuyaSerial->write((uint8_t)0x03); // command 03 - set wifi state
+    TuyaSerial->write((uint8_t)0x00);
+    TuyaSerial->write((uint8_t)0x01); // following data length 0x01
+    TuyaSerial->write((uint8_t)0x03); // wifi state 4 (configured and connected)
+    TuyaSerial->write((uint8_t)0x06); // checksum:sum of all bytes in packet mod 256
+    TuyaSerial->flush();
+}
+
 void TuyaInit()
 {
   if (!Settings.param[P_TUYA_DIMMER_ID]) {
@@ -245,18 +264,24 @@ void TuyaInit()
   }
 }
 
+void TuyaResetWifi()
+{
+  if (!Settings.flag.button_restrict) {
+    char scmnd[20];
+    snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " %d", 2);
+    ExecuteCommand(scmnd, SRC_BUTTON);
+    tuya_wifi_state = false;
+  }
+}
+
 boolean TuyaButtonPressed()
 {
   if ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == lastbutton[XdrvMailbox.index])) {
 
     snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), XdrvMailbox.index +1);
     AddLog(LOG_LEVEL_DEBUG);
+    TuyaResetWifi();
 
-    if (!Settings.flag.button_restrict) {
-      char scmnd[20];
-      snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " %d", 2);
-      ExecuteCommand(scmnd, SRC_BUTTON);
-    }
   }
   return true;  // Serviced here
 }
@@ -288,6 +313,9 @@ boolean Xdrv16(byte function)
       case FUNC_BUTTON_PRESSED:
         result = TuyaButtonPressed();
         break;
+      case FUNC_EVERY_SECOND:
+        if(TuyaSerial && !tuya_wifi_state) { TuyaResetWifiLed(); }
+        break;
     }
   }
   return result;
diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino
index e4cccb273..137bd82b1 100644
--- a/sonoff/xdrv_17_rcswitch.ino
+++ b/sonoff/xdrv_17_rcswitch.ino
@@ -1,7 +1,7 @@
 /*
   xdrv_17_rcswitch.ino - RF transceiver using RcSwitch library for Sonoff-Tasmota
 
-  Copyright (C) 2017  Theo Arends
+  Copyright (C) 2018  Theo Arends
 
   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
diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino
index 8a50b8ae6..23ddf7da9 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,28 @@
 
 #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_once = 1;
 
-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
@@ -73,75 +83,86 @@ float bmp_humidity = 0.0;
 
 #define BMP180_OSS           3
 
-int16_t  cal_ac1;
-int16_t  cal_ac2;
-int16_t  cal_ac3;
-int16_t  cal_b1;
-int16_t  cal_b2;
-int16_t  cal_mc;
-int16_t  cal_md;
-uint16_t cal_ac4;
-uint16_t cal_ac5;
-uint16_t cal_ac6;
+struct BMP180CALIBDATA {
+  int16_t  cal_ac1;
+  int16_t  cal_ac2;
+  int16_t  cal_ac3;
+  int16_t  cal_b1;
+  int16_t  cal_b2;
+  int16_t  cal_mc;
+  int16_t  cal_md;
+  uint16_t cal_ac4;
+  uint16_t cal_ac5;
+  uint16_t cal_ac6;
+} bmp180_cal_data[BMP_MAX_SENSORS];
 
-boolean Bmp180Calibration()
+boolean Bmp180Calibration(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);
+  bmp180_cal_data[bmp_idx].cal_ac1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC1);
+  bmp180_cal_data[bmp_idx].cal_ac2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC2);
+  bmp180_cal_data[bmp_idx].cal_ac3 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC3);
+  bmp180_cal_data[bmp_idx].cal_ac4 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC4);
+  bmp180_cal_data[bmp_idx].cal_ac5 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC5);
+  bmp180_cal_data[bmp_idx].cal_ac6 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC6);
+  bmp180_cal_data[bmp_idx].cal_b1  = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB1);
+  bmp180_cal_data[bmp_idx].cal_b2  = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB2);
+  bmp180_cal_data[bmp_idx].cal_mc  = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_MC);
+  bmp180_cal_data[bmp_idx].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) {
+  if (!bmp180_cal_data[bmp_idx].cal_ac1 |
+      !bmp180_cal_data[bmp_idx].cal_ac2 |
+      !bmp180_cal_data[bmp_idx].cal_ac3 |
+      !bmp180_cal_data[bmp_idx].cal_ac4 |
+      !bmp180_cal_data[bmp_idx].cal_ac5 |
+      !bmp180_cal_data[bmp_idx].cal_ac6 |
+      !bmp180_cal_data[bmp_idx].cal_b1 |
+      !bmp180_cal_data[bmp_idx].cal_b2 |
+      !bmp180_cal_data[bmp_idx].cal_mc |
+      !bmp180_cal_data[bmp_idx].cal_md) {
     return false;
   }
 
-  if ((cal_ac1 == (int16_t)0xFFFF) |
-      (cal_ac2 == (int16_t)0xFFFF) |
-      (cal_ac3 == (int16_t)0xFFFF) |
-      (cal_ac4 == 0xFFFF) |
-      (cal_ac5 == 0xFFFF) |
-      (cal_ac6 == 0xFFFF) |
-      (cal_b1 == (int16_t)0xFFFF) |
-      (cal_b2 == (int16_t)0xFFFF) |
-      (cal_mc == (int16_t)0xFFFF) |
-      (cal_md == (int16_t)0xFFFF)) {
+  if ((bmp180_cal_data[bmp_idx].cal_ac1 == (int16_t)0xFFFF) |
+      (bmp180_cal_data[bmp_idx].cal_ac2 == (int16_t)0xFFFF) |
+      (bmp180_cal_data[bmp_idx].cal_ac3 == (int16_t)0xFFFF) |
+      (bmp180_cal_data[bmp_idx].cal_ac4 == 0xFFFF) |
+      (bmp180_cal_data[bmp_idx].cal_ac5 == 0xFFFF) |
+      (bmp180_cal_data[bmp_idx].cal_ac6 == 0xFFFF) |
+      (bmp180_cal_data[bmp_idx].cal_b1 == (int16_t)0xFFFF) |
+      (bmp180_cal_data[bmp_idx].cal_b2 == (int16_t)0xFFFF) |
+      (bmp180_cal_data[bmp_idx].cal_mc == (int16_t)0xFFFF) |
+      (bmp180_cal_data[bmp_idx].cal_md == (int16_t)0xFFFF)) {
     return false;
   }
   return true;
 }
 
-void Bmp180Read()
+void Bmp180Read(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);
-  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);
+  int ut = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT);
+  int32_t xt1 = (ut - (int32_t)bmp180_cal_data[bmp_idx].cal_ac6) * ((int32_t)bmp180_cal_data[bmp_idx].cal_ac5) >> 15;
+  int32_t xt2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_mc << 11) / (xt1 + (int32_t)bmp180_cal_data[bmp_idx].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;
-  int32_t x1 = ((int32_t)cal_b2 * ((b6 * b6) >> 12)) >> 11;
-  int32_t x2 = ((int32_t)cal_ac2 * b6) >> 11;
+  int32_t x1 = ((int32_t)bmp180_cal_data[bmp_idx].cal_b2 * ((b6 * b6) >> 12)) >> 11;
+  int32_t x2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_ac2 * b6) >> 11;
   int32_t x3 = x1 + x2;
-  int32_t b3 = ((((int32_t)cal_ac1 * 4 + x3) << BMP180_OSS) + 2) >> 2;
+  int32_t b3 = ((((int32_t)bmp180_cal_data[bmp_idx].cal_ac1 * 4 + x3) << BMP180_OSS) + 2) >> 2;
 
-  x1 = ((int32_t)cal_ac3 * b6) >> 13;
-  x2 = ((int32_t)cal_b1 * ((b6 * b6) >> 12)) >> 16;
+  x1 = ((int32_t)bmp180_cal_data[bmp_idx].cal_ac3 * b6) >> 13;
+  x2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_b1 * ((b6 * b6) >> 12)) >> 16;
   x3 = ((x1 + x2) + 2) >> 2;
-  uint32_t b4 = ((uint32_t)cal_ac4 * (uint32_t)(x3 + 32768)) >> 15;
+  uint32_t b4 = ((uint32_t)bmp180_cal_data[bmp_idx].cal_ac4 * (uint32_t)(x3 + 32768)) >> 15;
   uint32_t b7 = ((uint32_t)up - b3) * (uint32_t)(50000UL >> BMP180_OSS);
 
   int32_t p;
@@ -155,7 +176,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
 }
 
 /*********************************************************************************************\
@@ -204,97 +225,96 @@ struct BME280CALIBDATA
   int16_t  dig_P7;
   int16_t  dig_P8;
   int16_t  dig_P9;
-  uint8_t  dig_H1;
   int16_t  dig_H2;
-  uint8_t  dig_H3;
   int16_t  dig_H4;
   int16_t  dig_H5;
+  uint8_t  dig_H1;
+  uint8_t  dig_H3;
   int8_t   dig_H6;
-} Bme280CalibrationData;
+} Bme280CalibrationData[BMP_MAX_SENSORS];
 
-boolean Bmx280Calibrate()
+boolean Bmx280Calibrate(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);
-
-    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)
+  Bme280CalibrationData[bmp_idx].dig_T1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T1);
+  Bme280CalibrationData[bmp_idx].dig_T2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T2);
+  Bme280CalibrationData[bmp_idx].dig_T3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T3);
+  Bme280CalibrationData[bmp_idx].dig_P1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P1);
+  Bme280CalibrationData[bmp_idx].dig_P2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P2);
+  Bme280CalibrationData[bmp_idx].dig_P3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P3);
+  Bme280CalibrationData[bmp_idx].dig_P4 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P4);
+  Bme280CalibrationData[bmp_idx].dig_P5 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P5);
+  Bme280CalibrationData[bmp_idx].dig_P6 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P6);
+  Bme280CalibrationData[bmp_idx].dig_P7 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P7);
+  Bme280CalibrationData[bmp_idx].dig_P8 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P8);
+  Bme280CalibrationData[bmp_idx].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[bmp_idx].dig_H1 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H1);
+    Bme280CalibrationData[bmp_idx].dig_H2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H2);
+    Bme280CalibrationData[bmp_idx].dig_H3 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H3);
+    Bme280CalibrationData[bmp_idx].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[bmp_idx].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[bmp_idx].dig_H6 = (int8_t)I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H6);
+    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 Bme280Read(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;
-  int32_t vart2 = (((((adc_T >> 4) - ((int32_t)Bme280CalibrationData.dig_T1)) * ((adc_T >> 4) - ((int32_t)Bme280CalibrationData.dig_T1))) >> 12) *
-    ((int32_t)Bme280CalibrationData.dig_T3)) >> 14;
+  int32_t vart1 = ((((adc_T >> 3) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1 << 1))) * ((int32_t)Bme280CalibrationData[bmp_idx].dig_T2)) >> 11;
+  int32_t vart2 = (((((adc_T >> 4) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1)) * ((adc_T >> 4) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1))) >> 12) *
+    ((int32_t)Bme280CalibrationData[bmp_idx].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;
-  int64_t var2 = var1 * var1 * (int64_t)Bme280CalibrationData.dig_P6;
-  var2 = var2 + ((var1 * (int64_t)Bme280CalibrationData.dig_P5) << 17);
-  var2 = var2 + (((int64_t)Bme280CalibrationData.dig_P4) << 35);
-  var1 = ((var1 * var1 * (int64_t)Bme280CalibrationData.dig_P3) >> 8) + ((var1 * (int64_t)Bme280CalibrationData.dig_P2) << 12);
-  var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)Bme280CalibrationData.dig_P1) >> 33;
+  int64_t var2 = var1 * var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P6;
+  var2 = var2 + ((var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P5) << 17);
+  var2 = var2 + (((int64_t)Bme280CalibrationData[bmp_idx].dig_P4) << 35);
+  var1 = ((var1 * var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P3) >> 8) + ((var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P2) << 12);
+  var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)Bme280CalibrationData[bmp_idx].dig_P1) >> 33;
   if (0 == var1) {
     return; // avoid exception caused by division by zero
   }
   int64_t p = 1048576 - adc_P;
   p = (((p << 31) - var2) * 3125) / var1;
-  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;
+  var1 = (((int64_t)Bme280CalibrationData[bmp_idx].dig_P9) * (p >> 13) * (p >> 13)) >> 25;
+  var2 = (((int64_t)Bme280CalibrationData[bmp_idx].dig_P8) * p) >> 19;
+  p = ((p + var1 + var2) >> 8) + (((int64_t)Bme280CalibrationData[bmp_idx].dig_P7) << 4);
+  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) -
-    (((int32_t)Bme280CalibrationData.dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) *
-    (((((((v_x1_u32r * ((int32_t)Bme280CalibrationData.dig_H6)) >> 10) *
-    (((v_x1_u32r * ((int32_t)Bme280CalibrationData.dig_H3)) >> 11) + ((int32_t)32768))) >> 10) +
-    ((int32_t)2097152)) * ((int32_t)Bme280CalibrationData.dig_H2) + 8192) >> 14));
+  v_x1_u32r = (((((adc_H << 14) - (((int32_t)Bme280CalibrationData[bmp_idx].dig_H4) << 20) -
+    (((int32_t)Bme280CalibrationData[bmp_idx].dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) *
+    (((((((v_x1_u32r * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H6)) >> 10) *
+    (((v_x1_u32r * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H3)) >> 11) + ((int32_t)32768))) >> 10) +
+    ((int32_t)2097152)) * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H2) + 8192) >> 14));
   v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *
-    ((int32_t)Bme280CalibrationData.dig_H1)) >> 4));
+    ((int32_t)Bme280CalibrationData[bmp_idx].dig_H1)) >> 4));
   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
@@ -304,92 +324,89 @@ void Bme280Read(void)
 
 #include <bme680.h>
 
-struct bme680_dev gas_sensor;
-
-float bmp_gas_resistance = 0.0;
-uint8_t bme680_state = 0;
+struct bme680_dev gas_sensor[BMP_MAX_SENSORS];
 
 static void BmeDelayMs(uint32_t ms)
 {
   delay(ms);
 }
 
-boolean Bme680Init()
+boolean Bme680Init(uint8_t bmp_idx)
 {
-  gas_sensor.dev_id = bmp_address;
-  gas_sensor.intf = BME680_I2C_INTF;
-  gas_sensor.read = &I2cReadBuffer;
-  gas_sensor.write = &I2cWriteBuffer;
-  gas_sensor.delay_ms = BmeDelayMs;
+  gas_sensor[bmp_idx].dev_id = bmp_sensors[bmp_idx].bmp_address;
+  gas_sensor[bmp_idx].intf = BME680_I2C_INTF;
+  gas_sensor[bmp_idx].read = &I2cReadBuffer;
+  gas_sensor[bmp_idx].write = &I2cWriteBuffer;
+  gas_sensor[bmp_idx].delay_ms = BmeDelayMs;
   /* amb_temp can be set to 25 prior to configuring the gas sensor
    * or by performing a few temperature readings without operating the gas sensor.
    */
-  gas_sensor.amb_temp = 25;
+  gas_sensor[bmp_idx].amb_temp = 25;
 
   int8_t rslt = BME680_OK;
-  rslt = bme680_init(&gas_sensor);
+  rslt = bme680_init(&gas_sensor[bmp_idx]);
   if (rslt != BME680_OK) { return false; }
 
   /* Set the temperature, pressure and humidity settings */
-  gas_sensor.tph_sett.os_hum = BME680_OS_2X;
-  gas_sensor.tph_sett.os_pres = BME680_OS_4X;
-  gas_sensor.tph_sett.os_temp = BME680_OS_8X;
-  gas_sensor.tph_sett.filter = BME680_FILTER_SIZE_3;
+  gas_sensor[bmp_idx].tph_sett.os_hum = BME680_OS_2X;
+  gas_sensor[bmp_idx].tph_sett.os_pres = BME680_OS_4X;
+  gas_sensor[bmp_idx].tph_sett.os_temp = BME680_OS_8X;
+  gas_sensor[bmp_idx].tph_sett.filter = BME680_FILTER_SIZE_3;
 
   /* Set the remaining gas sensor settings and link the heating profile */
-  gas_sensor.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS;
+  gas_sensor[bmp_idx].gas_sett.run_gas = BME680_ENABLE_GAS_MEAS;
   /* Create a ramp heat waveform in 3 steps */
-  gas_sensor.gas_sett.heatr_temp = 320; /* degree Celsius */
-  gas_sensor.gas_sett.heatr_dur = 150; /* milliseconds */
+  gas_sensor[bmp_idx].gas_sett.heatr_temp = 320; /* degree Celsius */
+  gas_sensor[bmp_idx].gas_sett.heatr_dur = 150; /* milliseconds */
 
   /* Select the power mode */
   /* Must be set before writing the sensor configuration */
-  gas_sensor.power_mode = BME680_FORCED_MODE;
+  gas_sensor[bmp_idx].power_mode = BME680_FORCED_MODE;
 
   /* Set the required sensor settings needed */
   uint8_t set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL;
 
   /* Set the desired sensor configuration */
-  rslt = bme680_set_sensor_settings(set_required_settings,&gas_sensor);
+  rslt = bme680_set_sensor_settings(set_required_settings,&gas_sensor[bmp_idx]);
   if (rslt != BME680_OK) { return false; }
 
-  bme680_state = 0;
+  bmp_sensors[bmp_idx].bme680_state = 0;
 
   return true;
 }
 
-void Bme680Read()
+void Bme680Read(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);
+      rslt = bme680_set_sensor_mode(&gas_sensor[bmp_idx]);
       if (rslt != BME680_OK) { return; }
 
       /* Get the total measurement duration so as to sleep or wait till the
        * measurement is complete */
 //      uint16_t meas_period;
-//      bme680_get_profile_dur(&meas_period, &gas_sensor);
+//      bme680_get_profile_dur(&meas_period, &gas_sensor[bmp_idx]);
 //      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);
+      rslt = bme680_get_sensor_data(&data, &gas_sensor[bmp_idx]);
       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 +419,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;
+      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 = Bmp180Calibration(bmp_count);
+          break;
+        case BME280_CHIPID:
+          bmp_sensors[bmp_count].bmp_model++;  // 2
+        case BMP280_CHIPID:
+          bmp_sensors[bmp_count].bmp_model++;  // 1
+          success = Bmx280Calibrate(bmp_count);
+          break;
 #ifdef USE_BME680
-      case BME680_CHIPID:
-        bmp_model = 3;  // 3
-        success = Bme680Init();
-        break;
+        case BME680_CHIPID:
+          bmp_sensors[bmp_count].bmp_model = 3;  // 3
+          success = Bme680Init(bmp_count);
+          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;
+      }
+      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;
+  for (byte bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) {
+    switch (bmp_sensors[bmp_idx].bmp_type) {
+      case BMP180_CHIPID:
+        Bmp180Read(bmp_idx);
+        break;
+      case BMP280_CHIPID:
+      case BME280_CHIPID:
+        Bme280Read(bmp_idx);
+        break;
 #ifdef USE_BME680
-    case BME680_CHIPID:
-      Bme680Read();
-      break;
+      case BME680_CHIPID:
+        Bme680Read(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 +495,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;
       }
-#endif // USE_DOMOTICZ
+
+      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
+#endif  // USE_WEBSERVER
+      }
     }
   }
 }
@@ -572,11 +609,11 @@ boolean Xsns09(byte function)
       case FUNC_WEB_APPEND:
         BmpShow(0);
         break;
-#endif // USE_WEBSERVER
+#endif  // USE_WEBSERVER
     }
   }
   return result;
 }
 
-#endif // USE_BMP
-#endif // USE_I2C
+#endif  // USE_BMP
+#endif  // USE_I2C