diff --git a/README.md b/README.md
index 77598acc2..a48256766 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
## Sonoff-Tasmota
Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE.
-Current version is **5.11.1a** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
+Current version is **5.11.1b** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
### ATTENTION All versions
diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino
index c4ed9770b..86ec89408 100644
--- a/sonoff/_releasenotes.ino
+++ b/sonoff/_releasenotes.ino
@@ -1,5 +1,13 @@
-/* 5.11.1a
- * Add automagic two step Web server OTA upgrade using filename-minimal image if OTA free space is too small
+/* 5.11.1b
+ * Add command PowerOnState option 5 which inverts PulseTime and allows for delayed always on after power on
+ * Changed OSWATCH_RESET_TIME (Blocked loop) from 30 to 120 seconds to allow slow networks (#1556)
+ * Add French language file (#1561)
+ * Fix truncated command names and wrong response for DomoticzSwitchIdx (#1571)
+ * Add HTTP Allow Cross Origin removed from ESP8266/Arduino 2.4.0 (#1572)
+ * Fix %-sign issue as printf escape character in Humidity and Sonoff SC (#1579)
+ *
+ * 5.11.1a
+ * Add OtaMagic two step Web server OTA upgrade using filename-minimal image if OTA free space is too small
* Add chinese language file (#1551)
*
* 5.11.1 20180107
diff --git a/sonoff/i18n.h b/sonoff/i18n.h
index 89e6951e1..bcdf337ac 100644
--- a/sonoff/i18n.h
+++ b/sonoff/i18n.h
@@ -423,7 +423,7 @@ static const char kMonthNames[] = D_MONTH3LIST;
// webserver.ino
#ifdef USE_WEBSERVER
const char HTTP_SNS_TEMP[] PROGMEM = "%s{s}%s " D_TEMPERATURE "{m}%s°%c{e}"; // {s} =
, {m} = | , {e} = |
-const char HTTP_SNS_HUM[] PROGMEM = "%s{s}%s " D_HUMIDITY "{m}%s%{e}"; // {s} = , {m} = | , {e} = |
+const char HTTP_SNS_HUM[] PROGMEM = "%s{s}%s " D_HUMIDITY "{m}%s%%{e}"; // {s} = , {m} = | , {e} = |
const char HTTP_SNS_PRESSURE[] PROGMEM = "%s{s}%s " D_PRESSURE "{m}%s " D_UNIT_PRESSURE "{e}"; // {s} = , {m} = | , {e} = |
const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "%s{s}%s " D_PRESSUREATSEALEVEL "{m}%s " D_UNIT_PRESSURE "{e}"; // {s} = , {m} = | , {e} = |
const char HTTP_SNS_ANALOG[] PROGMEM = "%s{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = , {m} = | , {e} = |
diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h
new file mode 100644
index 000000000..25b41c67b
--- /dev/null
+++ b/sonoff/language/fr-FR.h
@@ -0,0 +1,469 @@
+/*
+ fr-FR.h - localization for French - France for Sonoff-Tasmota
+
+ Copyright (C) 2018 Olivier Francais
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _LANGUAGE_FR_FR_H_
+#define _LANGUAGE_FR_FR_H_
+
+/*************************** ATTENTION *******************************\
+ *
+ * Due to memory constraints only UTF-8 is supported.
+ * To save code space keep text as short as possible.
+ * Time and Date provided by SDK can not be localized (yet).
+ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
+ * Use online command Prefix to translate cmnd, stat and tele.
+ *
+\*********************************************************************/
+
+// "2017-03-07T11:08:02" - ISO8601:2004
+#define D_YEAR_MONTH_SEPARATOR "-"
+#define D_MONTH_DAY_SEPARATOR "-"
+#define D_DATE_TIME_SEPARATOR "T"
+#define D_HOUR_MINUTE_SEPARATOR ":"
+#define D_MINUTE_SECOND_SEPARATOR ":"
+
+#define D_DAY3LIST "DimLunMarMerJeuVenSam"
+#define D_MONTH3LIST "JanFevMarAvrMaiJunJulAutSepOctNovDec"
+
+// Non JSON decimal separator
+#define D_DECIMAL_SEPARATOR ","
+
+// Common
+#define D_ADMIN "Admin"
+#define D_AIR_QUALITY "Qualité de l'Air"
+#define D_AP "AP" // Access Point
+#define D_AS "comme"
+#define D_AUTO "AUTO"
+#define D_BLINK "Blink"
+#define D_BLINKOFF "BlinkOff"
+#define D_BOOT_COUNT "Nombre de boot"
+#define D_BRIGHTLIGHT "Luminosité"
+#define D_BUTTON "Boutton"
+#define D_BY "par" // Written by me
+#define D_BYTES "Bytes"
+#define D_CELSIUS "Celsius"
+#define D_CO2 "Dioxyde arbone"
+#define D_CODE "code" // Button code
+#define D_COLDLIGHT "Froid"
+#define D_COMMAND "Commande"
+#define D_CONNECTED "Connecté"
+#define D_COUNT "Compte"
+#define D_COUNTER "Compteur"
+#define D_CURRENT "Courrant" // As in Voltage and Current
+#define D_DATA "Data"
+#define D_DARKLIGHT "Sombre"
+#define D_DEBUG "Debug"
+#define D_DISABLED "Désactivé"
+#define D_DNS_SERVER "Serveur DNS"
+#define D_DONE "Fait"
+#define D_DST_TIME "DST"
+#define D_EMULATION "Emulation"
+#define D_ENABLED "Activé"
+#define D_ERASE "Effacer"
+#define D_ERROR "Erreur"
+#define D_FAHRENHEIT "Fahrenheit"
+#define D_FAILED "Echoué"
+#define D_FALLBACK "Fallback"
+#define D_FALLBACK_TOPIC "Fallback Topic"
+#define D_FALSE "Faux"
+#define D_FILE "Fichier"
+#define D_FREE_MEMORY "Memoire libre"
+#define D_GAS "Gaz"
+#define D_GATEWAY "Passerelle"
+#define D_GROUP "Groupe"
+#define D_HOST "Host"
+#define D_HOSTNAME "Hostname"
+#define D_HUMIDITY "Humidité"
+#define D_ILLUMINANCE "Éclairement"
+#define D_IMMEDIATE "immediat" // Button immediate
+#define D_INDEX "Index"
+#define D_INFO "Info"
+#define D_INITIALIZED "Initialisé"
+#define D_IP_ADDRESS "Adresse IP"
+#define D_LIGHT "Lumière"
+#define D_LWT "LWT"
+#define D_MODULE "Module"
+#define D_MQTT "MQTT"
+#define D_MULTI_PRESS "multi-pression"
+#define D_NOISE "Bruit"
+#define D_NONE "None"
+#define D_OFF "Off"
+#define D_OFFLINE "Déconnecté"
+#define D_OK "Ok"
+#define D_ON "On"
+#define D_ONLINE "Connecté"
+#define D_PASSWORD "Mot de passe"
+#define D_PORT "Port"
+#define D_POWER_FACTOR "Facteur de puissance"
+#define D_POWERUSAGE "Puissance"
+#define D_PRESSURE "Pression"
+#define D_PRESSUREATSEALEVEL "PressionMer"
+#define D_PROGRAM_FLASH_SIZE "Taille Flash Programme"
+#define D_PROGRAM_SIZE "Taille programme"
+#define D_PROJECT "Projet"
+#define D_RECEIVED "Reçu"
+#define D_RESTART "Redémarrage"
+#define D_RESTARTING "Redémarrage"
+#define D_RESTART_REASON "Raison redémarrage"
+#define D_RESTORE "restorer"
+#define D_RETAINED "retenu"
+#define D_SAVE "Enregister"
+#define D_SENSOR "Capteur"
+#define D_SSID "SSID"
+#define D_START "Start"
+#define D_STD_TIME "STD"
+#define D_STOP "Stop"
+#define D_SUBNET_MASK "Masque sous réseau"
+#define D_SUBSCRIBE_TO "Souscrire à"
+#define D_SUCCESSFUL "Réussi"
+#define D_TEMPERATURE "Temperature"
+#define D_TO "à"
+#define D_TOGGLE "Bascule"
+#define D_TOPIC "Topic"
+#define D_TRANSMIT "Transmettre"
+#define D_TRUE "Vrai"
+#define D_UPGRADE "upgrade"
+#define D_UPLOAD "Upload"
+#define D_UPTIME "Uptime"
+#define D_USER "Utilisateur"
+#define D_UTC_TIME "UTC"
+#define D_UV_LEVEL "Niveau UV"
+#define D_VERSION "Version"
+#define D_VOLTAGE "Voltage"
+#define D_WARMLIGHT "Chaud"
+#define D_WEB_SERVER "Serveur web"
+
+// sonoff.ino
+#define D_WARNING_MINIMAL_VERSION "WARNING This version does not support persistent settings"
+#define D_LEVEL_10 "level 1-0"
+#define D_LEVEL_01 "level 0-1"
+#define D_SERIAL_LOGGING_DISABLED "Journalisation série désactivé"
+#define D_SYSLOG_LOGGING_REENABLED "Jounalisation syslog réactivé"
+
+#define D_SET_BAUDRATE_TO "Definir baudrate à"
+#define D_RECEIVED_TOPIC "Topic reçu"
+#define D_DATA_SIZE "Taille données"
+#define D_ANALOG_INPUT "Analogique"
+
+#define D_FINGERPRINT "Verification empreinte TLS ..."
+#define D_TLS_CONNECT_FAILED_TO "Echec de connexion TLS à"
+#define D_RETRY_IN "Nouvelle tentative dans"
+#define D_VERIFIED "Verifié"
+#define D_INSECURE "Connexion non sécurisée car empreinte non vérifée"
+#define D_CONNECT_FAILED_TO "Echec de connexion à"
+
+// support.ino
+#define D_OSWATCH "osWatch"
+#define D_BLOCKED_LOOP "Boucle bloquée"
+#define D_WPS_FAILED_WITH_STATUS "WPSconfig ECHOUÉ avec status"
+#define D_ACTIVE_FOR_3_MINUTES "actif pour 3 minutes"
+#define D_FAILED_TO_START "Echec de démarrage"
+#define D_PATCH_ISSUE_2186 "Patch issue 2186"
+#define D_CONNECTING_TO_AP "Connexion à l'AP"
+#define D_IN_MODE "en mode"
+#define D_CONNECT_FAILED_NO_IP_ADDRESS "Echec de connexion car aucune adresse IP n'a été reçue"
+#define D_CONNECT_FAILED_AP_NOT_REACHED "Echec de connexion car l'AP ne peut-être contacté"
+#define D_CONNECT_FAILED_WRONG_PASSWORD "Echec de connexion car le mot de passe de l'AP est incorrect"
+#define D_CONNECT_FAILED_AP_TIMEOUT "Echec de connexion avec l'AP, expiré"
+#define D_ATTEMPTING_CONNECTION "Tentative de connexion..."
+#define D_CHECKING_CONNECTION "Verification connexion..."
+#define D_QUERY_DONE "Requête terminé. Services MQTT trouvés"
+#define D_MQTT_SERVICE_FOUND "Service MQTT trouvé sur"
+#define D_FOUND_AT "trouvé à"
+#define D_SYSLOG_HOST_NOT_FOUND "Host syslog introuvable"
+
+// settings.ino
+#define D_SAVED_TO_FLASH_AT "Enregistré dans la flash à"
+#define D_LOADED_FROM_FLASH_AT "Chargé de la flash à"
+#define D_USE_DEFAULTS "Utiliser par défaut"
+#define D_ERASED_SECTOR "Secteur effacé"
+
+// webserver.ino
+#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMAL - merci de mettre à jour"
+#define D_WEBSERVER_ACTIVE_ON "Serveur web actif sur"
+#define D_WITH_IP_ADDRESS "avec l'adresse IP"
+#define D_WEBSERVER_STOPPED "Serveur web éteint"
+#define D_FILE_NOT_FOUND "Fichier introuvable"
+#define D_REDIRECTED "Redirection sur le portail captif"
+#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager defini AccessPoint et garde station"
+#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager defini AccessPoint"
+#define D_TRYING_TO_CONNECT "Tentative de connexion du module au réseau"
+
+#define D_RESTART_IN "Redémarrage dans"
+#define D_SECONDS "secondes"
+#define D_DEVICE_WILL_RESTART "Le module va redémarrer dans quelques secondes"
+#define D_BUTTON_TOGGLE "on/off"
+#define D_CONFIGURATION "Configuration"
+#define D_INFORMATION "Information"
+#define D_FIRMWARE_UPGRADE "Mise à jour Firmware"
+#define D_CONSOLE "Console"
+#define D_CONFIRM_RESTART "Confirmer redémarrage"
+
+#define D_CONFIGURE_MODULE "Configuration Module"
+#define D_CONFIGURE_WIFI "Configuration WiFi"
+#define D_CONFIGURE_MQTT "Configuration MQTT"
+#define D_CONFIGURE_DOMOTICZ "Configuration Domoticz"
+#define D_CONFIGURE_LOGGING "Configuration Logging"
+#define D_CONFIGURE_OTHER "Autre configuration"
+#define D_CONFIRM_RESET_CONFIGURATION "Confirmer réinitialisation configuration"
+#define D_RESET_CONFIGURATION "Réinitialisation Configuration"
+#define D_BACKUP_CONFIGURATION "Sauvegarde Configuration"
+#define D_RESTORE_CONFIGURATION "Restauration Configuration"
+#define D_MAIN_MENU "Menu principal"
+
+#define D_MODULE_PARAMETERS "Paramètres module"
+#define D_MODULE_TYPE "Type module"
+#define D_GPIO "GPIO"
+#define D_SERIAL_IN "Serial In"
+#define D_SERIAL_OUT "Serial Out"
+
+#define D_WIFI_PARAMETERS "Paramètres Wifi"
+#define D_SCAN_FOR_WIFI_NETWORKS "Scan des réseaux wifi"
+#define D_SCAN_DONE "Scan terminé"
+#define D_NO_NETWORKS_FOUND "Aucun réseau trouvé"
+#define D_REFRESH_TO_SCAN_AGAIN "Rafraichir pour scanner à nouveau"
+#define D_DUPLICATE_ACCESSPOINT "AccessPoint dupliqué"
+#define D_SKIPPING_LOW_QUALITY "Passe car mauvaise qualité"
+#define D_RSSI "RSSI"
+#define D_WEP "WEP"
+#define D_WPA_PSK "WPA PSK"
+#define D_WPA2_PSK "WPA2 PSK"
+#define D_AP1_SSID "AP1 SSID"
+#define D_AP1_PASSWORD "Mot de passe AP1"
+#define D_AP2_SSID "AP2 SSId"
+#define D_AP2_PASSWORD "Mot de passe AP2"
+
+#define D_MQTT_PARAMETERS "Paramètres MQTT"
+#define D_CLIENT "Client"
+#define D_FULL_TOPIC "topic complet"
+
+#define D_LOGGING_PARAMETERS "Paramètres journalisation"
+#define D_SERIAL_LOG_LEVEL "Niveau de journalisation série"
+#define D_WEB_LOG_LEVEL "Niveau de journalisation web"
+#define D_SYS_LOG_LEVEL "Niveau syslog"
+#define D_MORE_DEBUG "Plus de debug"
+#define D_SYSLOG_HOST "Host syslog"
+#define D_SYSLOG_PORT "Host syslog"
+#define D_TELEMETRY_PERIOD "Période télémetrie"
+
+#define D_OTHER_PARAMETERS "Autres paramètres"
+#define D_WEB_ADMIN_PASSWORD "Mot de passe Web Admin"
+#define D_MQTT_ENABLE "MQTT activé"
+#define D_FRIENDLY_NAME "Nom d'usage"
+#define D_BELKIN_WEMO "Belkin WeMo"
+#define D_HUE_BRIDGE "Hue Bridge"
+#define D_SINGLE_DEVICE "module unique"
+#define D_MULTI_DEVICE "multi module"
+
+#define D_SAVE_CONFIGURATION "Enregistrer configuration"
+#define D_CONFIGURATION_SAVED "Configuration enregistré"
+#define D_CONFIGURATION_RESET "Configuration réinitialisé"
+
+#define D_PROGRAM_VERSION "Version Programme"
+#define D_BUILD_DATE_AND_TIME "Date & Heure de build"
+#define D_CORE_AND_SDK_VERSION "Version Core/SDK"
+#define D_FLASH_WRITE_COUNT "Compteur écriture flash"
+#define D_MAC_ADDRESS "Adresse MAC"
+#define D_MQTT_HOST "Hôte MQTT"
+#define D_MQTT_PORT "Port MQTT"
+#define D_MQTT_CLIENT "Client MQTT"
+#define D_MQTT_USER "Utilisateur MQTT"
+#define D_MQTT_TOPIC "Topic MQTT"
+#define D_MQTT_GROUP_TOPIC "Groupe topic MQTT"
+#define D_MQTT_FULL_TOPIC "Topic complet MQTT"
+#define D_MDNS_DISCOVERY "Découverte mDNS"
+#define D_MDNS_ADVERTISE "Annonce mDNS"
+#define D_ESP_CHIP_ID "ESP Chip Id"
+#define D_FLASH_CHIP_ID "Flash Chip Id"
+#define D_FLASH_CHIP_SIZE "Taille flash"
+#define D_FREE_PROGRAM_SPACE "Espace programme libre"
+
+#define D_UPGRADE_BY_WEBSERVER "Mise à jour par serveur web"
+#define D_OTA_URL "URL OTA"
+#define D_START_UPGRADE "Lancer la mise à jour"
+#define D_UPGRADE_BY_FILE_UPLOAD "Mise à jour par téléchargement fichier"
+#define D_UPLOAD_STARTED "Téléchargement lancé"
+#define D_UPGRADE_STARTED "Mise à jour lancé"
+#define D_UPLOAD_DONE "Téléchargement terminé"
+#define D_UPLOAD_ERR_1 "Aucun fichier sélectionné"
+#define D_UPLOAD_ERR_2 "Espace insuffisant"
+#define D_UPLOAD_ERR_3 "Magic byte n'est pas 0xE9"
+#define D_UPLOAD_ERR_4 "La taille de la flash programme est plus grande que la taille réelle de la flash"
+#define D_UPLOAD_ERR_5 "Erreur comparaison buffer de téléchargement"
+#define D_UPLOAD_ERR_6 "Téléchargement échoué. Activation logging 3"
+#define D_UPLOAD_ERR_7 "Téléchargement annulé"
+#define D_UPLOAD_ERR_8 "Fichier invalide"
+#define D_UPLOAD_ERR_9 "Fichier trop grand"
+#define D_UPLOAD_ERROR_CODE "Code d'erreur téléchargement"
+
+#define D_ENTER_COMMAND "Saisir commande"
+#define D_ENABLE_WEBLOG_FOR_RESPONSE "Activer weblog 2 si response attendue"
+#define D_NEED_USER_AND_PASSWORD "Nécessite utilisateur=&password="
+
+// xdrv_wemohue.ino
+#define D_MULTICAST_DISABLED "Multicast désactivé"
+#define D_MULTICAST_REJOINED "Multicast (re)joint"
+#define D_MULTICAST_JOIN_FAILED "Multicast echec abonnement"
+#define D_FAILED_TO_SEND_RESPONSE "Echec d'envoi réponse"
+
+#define D_WEMO "WeMo"
+#define D_WEMO_BASIC_EVENT "WeMo basic event"
+#define D_WEMO_EVENT_SERVICE "WeMo event service"
+#define D_WEMO_META_SERVICE "WeMo meta service"
+#define D_WEMO_SETUP "Réglage WeMo"
+#define D_RESPONSE_SENT "Response envoyé"
+
+#define D_HUE "Hue"
+#define D_HUE_BRIDGE_SETUP "Réglage Hue"
+#define D_HUE_API_NOT_IMPLEMENTED "API Hue non implémentée"
+#define D_HUE_API "Hue API"
+#define D_HUE_POST_ARGS "Hue POST args"
+#define D_3_RESPONSE_PACKETS_SENT "3 paquets response envoyés"
+
+// xdrv_02_irremote.ino
+#define D_JSON_INVALID_JSON "JSON Invalide"
+#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protocole non supporté"
+#define D_JSON_IR_PROTOCOL "PROTOCOL"
+#define D_JSON_IR_BITS "BITS"
+#define D_JSON_IR_DATA "DATA"
+#define D_JSON_IRHVAC_VENDOR "VENDOR"
+#define D_JSON_IRHVAC_POWER "POWER"
+#define D_JSON_IRHVAC_MODE "MODE"
+#define D_JSON_IRHVAC_FANSPEED "FANSPEED"
+#define D_JSON_IRHVAC_TEMP "TEMP"
+#define D_JSON_IRRECEIVED "IrReceived"
+
+// xdrv_05_domoticz.ino
+#define D_DOMOTICZ_PARAMETERS "Paramètres Domoticz"
+#define D_DOMOTICZ_IDX "Idx"
+#define D_DOMOTICZ_KEY_IDX "Key idx"
+#define D_DOMOTICZ_SWITCH_IDX "Switch idx"
+#define D_DOMOTICZ_SENSOR_IDX "Sensor idx"
+ #define D_DOMOTICZ_TEMP "Temp"
+ #define D_DOMOTICZ_TEMP_HUM "Temp,Hum"
+ #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro"
+ #define D_DOMOTICZ_POWER_ENERGY "Power,Energy"
+ #define D_DOMOTICZ_ILLUMINANCE "Illuminance"
+ #define D_DOMOTICZ_COUNT "Count"
+ #define D_DOMOTICZ_VOLTAGE "Voltage"
+ #define D_DOMOTICZ_CURRENT "Current"
+ #define D_DOMOTICZ_AIRQUALITY "AirQuality"
+#define D_DOMOTICZ_UPDATE_TIMER "Update timer"
+
+// xsns_03_energy.ino
+#define D_ENERGY_TODAY "Energie aujourd'hui"
+#define D_ENERGY_YESTERDAY "Energie hier"
+#define D_ENERGY_TOTAL "Energie totale"
+
+// xsns_05_ds18b20.ino
+#define D_SENSOR_BUSY "Capteur occupé"
+#define D_SENSOR_CRC_ERROR "Erreur CRC capteur"
+#define D_SENSORS_FOUND "Capteur trouvé"
+
+// xsns_06_dht.ino
+#define D_TIMEOUT_WAITING_FOR "Expiré attend pour"
+#define D_START_SIGNAL_LOW "Signal démarrage bas"
+#define D_START_SIGNAL_HIGH "Signal démarrage haut"
+#define D_PULSE "pulse"
+#define D_CHECKSUM_FAILURE "Echec checksum"
+
+// xsns_07_sht1x.ino
+#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command"
+#define D_SHT1X_FOUND "SHT1X found"
+
+// xsns_18_pms5003.ino
+#define D_STANDARD_CONCENTRATION "Standard Concentration"
+#define D_ENVIRONMENTAL_CONCENTRATION "Environmental Concentration"
+#define D_PARTICALS_BEYOND "Particals beyond"
+
+// sonoff_template.h
+// Max string length is 8 characters including suffixes
+#define D_SENSOR_NONE "None"
+#define D_SENSOR_DHT11 "DHT11"
+#define D_SENSOR_AM2301 "AM2301"
+#define D_SENSOR_SI7021 "SI7021"
+#define D_SENSOR_DS18X20 "DS18x20"
+#define D_SENSOR_I2C_SCL "I2C SCL"
+#define D_SENSOR_I2C_SDA "I2C SDA"
+#define D_SENSOR_WS2812 "WS2812"
+#define D_SENSOR_IRSEND "IRsend"
+#define D_SENSOR_SWITCH "Switch" // Suffix "1"
+#define D_SENSOR_BUTTON "Button" // Suffix "1"
+#define D_SENSOR_RELAY "Relay" // Suffix "1i"
+#define D_SENSOR_LED "LED" // Suffix "1i"
+#define D_SENSOR_PWM "PWM" // Suffix "1"
+#define D_SENSOR_COUNTER "Counter" // Suffix "1"
+#define D_SENSOR_IRRECV "IRrecv"
+#define D_SENSOR_MHZ_RX "MHZ Rx"
+#define D_SENSOR_MHZ_TX "MHZ Tx"
+#define D_SENSOR_PZEM_RX "PZEM Rx"
+#define D_SENSOR_PZEM_TX "PZEM Tx"
+#define D_SENSOR_SAIR_RX "SAir Rx"
+#define D_SENSOR_SAIR_TX "SAir Tx"
+#define D_SENSOR_SPI_CS "SPI CS"
+#define D_SENSOR_SPI_DC "SPI DC"
+#define D_SENSOR_BACKLIGHT "BkLight"
+#define D_SENSOR_PMS5003 "PMS5003"
+
+// Units
+#define D_UNIT_AMPERE "A"
+#define D_UNIT_HOUR "h"
+#define D_UNIT_KILOOHM "kOhm"
+#define D_UNIT_KILOWATTHOUR "kWh"
+#define D_UNIT_LUX "lx"
+#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3"
+#define D_UNIT_MICROMETER "um"
+#define D_UNIT_MICROSECOND "us"
+#define D_UNIT_MILLIAMPERE "mA"
+#define D_UNIT_MILLISECOND "ms"
+#define D_UNIT_MINUTE "Min"
+#define D_UNIT_PARTS_PER_DECILITER "ppd"
+#define D_UNIT_PARTS_PER_MILLION "ppm"
+#define D_UNIT_PRESSURE "hPa"
+#define D_UNIT_SECOND "sec"
+#define D_UNIT_SECTORS "secteurs"
+#define D_UNIT_VOLT "V"
+#define D_UNIT_WATT "W"
+#define D_UNIT_WATTHOUR "Wh"
+
+// Log message prefix
+#define D_LOG_APPLICATION "APP: " // Application
+#define D_LOG_BRIDGE "BRG: " // Bridge
+#define D_LOG_CONFIG "CFG: " // Settings
+#define D_LOG_COMMAND "CMD: " // Command
+#define D_LOG_DEBUG "DBG: " // Debug
+#define D_LOG_DHT "DHT: " // DHT sensor
+#define D_LOG_DOMOTICZ "DOM: " // Domoticz
+#define D_LOG_DSB "DSB: " // DS18xB20 sensor
+#define D_LOG_HTTP "HTP: " // HTTP webserver
+#define D_LOG_I2C "I2C: " // I2C
+#define D_LOG_IRR "IRR: " // Infra Red Received
+#define D_LOG_LOG "LOG: " // Logging
+#define D_LOG_MODULE "MOD: " // Module
+#define D_LOG_MDNS "DNS: " // mDNS
+#define D_LOG_MQTT "MQT: " // MQTT
+#define D_LOG_OTHER "OTH: " // Other
+#define D_LOG_RESULT "RSL: " // Result
+#define D_LOG_RFR "RFR: " // RF Received
+#define D_LOG_SERIAL "SER: " // Serial
+#define D_LOG_SHT1 "SHT: " // SHT1x sensor
+#define D_LOG_UPLOAD "UPL: " // Upload
+#define D_LOG_UPNP "UPP: " // UPnP
+#define D_LOG_WIFI "WIF: " // Wifi
+
+#endif // _LANGUAGE_FR_FR_H_
diff --git a/sonoff/settings.h b/sonoff/settings.h
index de6688563..381e7ee9f 100644
--- a/sonoff/settings.h
+++ b/sonoff/settings.h
@@ -44,7 +44,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint32_t ws_clock_reverse : 1; // bit 16 (v5.8.1)
uint32_t decimal_text : 1; // bit 17 (v5.8.1)
uint32_t light_signal : 1; // bit 18 (v5.10.0c)
- uint32_t spare19 : 1;
+ uint32_t hass_discovery : 1; // bit 19 (v5.11.1a)
uint32_t voltage_resolution : 1; // Replaced by below
uint32_t spare21 : 1;
uint32_t spare22 : 1;
diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h
index f6f580548..d6a7389dc 100644
--- a/sonoff/sonoff.h
+++ b/sonoff/sonoff.h
@@ -137,7 +137,7 @@ enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_R
enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX};
enum XsnsFunctions {FUNC_INIT, FUNC_EVERY_50_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART,
- FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR};
+ FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_CONNECTED, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR};
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino
index e848dda88..6be6edc11 100644
--- a/sonoff/sonoff.ino
+++ b/sonoff/sonoff.ino
@@ -25,7 +25,7 @@
- Select IDE Tools - Flash Size: "1M (no SPIFFS)"
====================================================*/
-#define VERSION 0x050B0101 // 5.11.1a
+#define VERSION 0x050B0102 // 5.11.1b
// Location specific includes
#include "sonoff.h" // Enumaration used in user_config.h
@@ -395,7 +395,7 @@ void MqttPublishPrefixTopic_P(uint8_t prefix, const char* subtopic, boolean reta
* prefix 5 = stat using subtopic or RESULT
* prefix 6 = tele using subtopic or RESULT
*/
- char romram[16];
+ char romram[33];
char stopic[TOPSZ];
snprintf_P(romram, sizeof(romram), ((prefix > 3) && !Settings.flag.mqtt_response) ? S_RSLT_RESULT : subtopic);
@@ -415,7 +415,7 @@ void MqttPublishPrefixTopic_P(uint8_t prefix, const char* subtopic)
void MqttPublishPowerState(byte device)
{
char stopic[TOPSZ];
- char scommand[16];
+ char scommand[33];
if ((device < 1) || (device > devices_present)) {
device = 1;
@@ -432,7 +432,7 @@ void MqttPublishPowerState(byte device)
void MqttPublishPowerBlinkState(byte device)
{
- char scommand[16];
+ char scommand[33];
if ((device < 1) || (device > devices_present)) {
device = 1;
@@ -920,12 +920,13 @@ void MqttDataCallback(char* topic, byte* data, unsigned int data_len)
}
else if ((CMND_POWERONSTATE == command_code) && (Settings.module != MOTOR)) {
/* 0 = Keep relays off after power on
- * 1 = Turn relays on after power on
+ * 1 = Turn relays on after power on, if PulseTime set wait for PulseTime seconds, and turn relays off
* 2 = Toggle relays after power on
* 3 = Set relays to last saved state after power on
* 4 = Turn relays on and disable any relay control (used for Sonoff Pow to always measure power)
+ * 5 = Keep relays off after power on, if PulseTime set wait for PulseTime seconds, and turn relays on
*/
- if ((payload >= 0) && (payload <= 4)) {
+ if ((payload >= 0) && (payload <= 5)) {
Settings.poweronstate = payload;
if (4 == Settings.poweronstate) {
for (byte i = 1; i <= devices_present; i++) {
@@ -971,7 +972,7 @@ void MqttDataCallback(char* topic, byte* data, unsigned int data_len)
}
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, (Settings.save_data > 1) ? stemp1 : GetStateText(Settings.save_data));
}
- else if ((CMND_SETOPTION == command_code) && ((index >= 0) && (index <= 18)) || ((index > 31) && (index <= P_MAX_PARAM8 +31))) {
+ else if ((CMND_SETOPTION == command_code) && ((index >= 0) && (index <= 19)) || ((index > 31) && (index <= P_MAX_PARAM8 +31))) {
if (index <= 31) {
ptype = 0; // SetOption0 .. 31
} else {
@@ -984,6 +985,7 @@ void MqttDataCallback(char* topic, byte* data, unsigned int data_len)
switch (index) {
case 3: // mqtt
case 15: // pwm_control
+ case 19: // hass_discovery
restart_flag = 2;
case 0: // save_state
case 1: // button_restrict
@@ -1608,7 +1610,8 @@ void ExecuteCommandPower(byte device, byte state)
DomoticzUpdatePowerState(device);
#endif // USE_DOMOTICZ
if (device <= MAX_PULSETIMERS) {
- pulse_timer[(device -1)] = (power & mask) ? Settings.pulse_timer[(device -1)] : 0;
+// pulse_timer[(device -1)] = (power & mask) ? Settings.pulse_timer[(device -1)] : 0;
+ pulse_timer[(device -1)] = (((5 == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[(device -1)] : 0;
}
}
else if (3 == state) { // Blink
@@ -1766,7 +1769,7 @@ void PublishStatus(uint8_t payload)
void MqttShowState()
{
- char stemp1[16];
+ char stemp1[33];
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_JSON_TIME "\":\"%s\",\"" D_JSON_UPTIME "\":%d"), mqtt_data, GetDateAndTime().c_str(), uptime);
#ifdef USE_ADC_VCC
@@ -2137,7 +2140,8 @@ void StateLoop()
if ((pulse_timer[i] > 0) && (pulse_timer[i] < 112)) {
pulse_timer[i]--;
if (!pulse_timer[i]) {
- ExecuteCommandPower(i +1, 0);
+// ExecuteCommandPower(i +1, 0);
+ ExecuteCommandPower(i +1, (5 == Settings.poweronstate) ? 1: 0);
}
}
}
@@ -2684,6 +2688,7 @@ void setup()
if ((resetInfo.reason == REASON_DEFAULT_RST) || (resetInfo.reason == REASON_EXT_SYS_RST)) {
switch (Settings.poweronstate) {
case 0: // All off
+ case 5: // All off but on after PulseTime
power = 0;
SetDevicePower(power);
break;
@@ -2717,7 +2722,8 @@ void setup()
if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) {
bitWrite(power, i, digitalRead(pin[GPIO_REL1 +i]) ^ bitRead(rel_inverted, i));
}
- if ((i < MAX_PULSETIMERS) && bitRead(power, i)) {
+// if ((i < MAX_PULSETIMERS) && bitRead(power, i)) {
+ if ((i < MAX_PULSETIMERS) && (bitRead(power, i) || (5 == Settings.poweronstate))) {
pulse_timer[i] = Settings.pulse_timer[i];
}
}
diff --git a/sonoff/support.ino b/sonoff/support.ino
index 166e1ad81..08476b2c9 100644
--- a/sonoff/support.ino
+++ b/sonoff/support.ino
@@ -26,7 +26,7 @@ unsigned long syslog_host_refresh = 0;
Ticker tickerOSWatch;
-#define OSWATCH_RESET_TIME 30
+#define OSWATCH_RESET_TIME 120
static unsigned long oswatch_last_loop_time;
byte oswatch_blocked_loop = 0;
diff --git a/sonoff/user_config.h b/sonoff/user_config.h
index f3f76b822..d35e643d6 100644
--- a/sonoff/user_config.h
+++ b/sonoff/user_config.h
@@ -29,11 +29,12 @@
\*********************************************************************************************/
// -- Localization --------------------------------
-//#define MY_LANGUAGE en-GB // English in Great Britain. Enabled by Default
-//#define MY_LANGUAGE nl-NL // Dutch in the Netherlands
//#define MY_LANGUAGE de-DE // German in Germany
-//#define MY_LANGUAGE pl-PL // Polish in Poland
+//#define MY_LANGUAGE en-GB // English in Great Britain. Enabled by Default
+//#define MY_LANGUAGE fr-FR // French in France
//#define MY_LANGUAGE it-IT // Italian in Italy
+//#define MY_LANGUAGE nl-NL // Dutch in the Netherlands
+//#define MY_LANGUAGE pl-PL // Polish in Poland
//#define MY_LANGUAGE zh-CN // Chinese (Simplified) in China
// -- Project -------------------------------------
diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino
index 2b095c31d..4537978e9 100644
--- a/sonoff/webserver.ino
+++ b/sonoff/webserver.ino
@@ -407,6 +407,9 @@ void SetHeader()
WebServer->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate"));
WebServer->sendHeader(F("Pragma"), F("no-cache"));
WebServer->sendHeader(F("Expires"), F("-1"));
+#ifndef ARDUINO_ESP8266_RELEASE_2_3_0
+ WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*"));
+#endif
}
void ShowPage(String &page)
@@ -885,10 +888,14 @@ void HandleOtherConfiguration()
page += FPSTR(HTTP_FORM_OTHER);
page.replace(F("{p1"), Settings.web_password);
page.replace(F("{r1"), (Settings.flag.mqtt_enabled) ? F(" checked") : F(""));
- page += FPSTR(HTTP_FORM_OTHER2);
- page.replace(F("{1"), F("1"));
- page.replace(F("{2"), FRIENDLY_NAME);
- page.replace(F("{3"), Settings.friendlyname[0]);
+ uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present;
+ for (byte i = 0; i < maxfn; i++) {
+ page += FPSTR(HTTP_FORM_OTHER2);
+ page.replace(F("{1"), String(i +1));
+ snprintf_P(stemp, sizeof(stemp), PSTR(FRIENDLY_NAME"%d"), i +1);
+ page.replace(F("{2"), (i) ? stemp : FRIENDLY_NAME);
+ page.replace(F("{3"), Settings.friendlyname[i]);
+ }
#ifdef USE_EMULATION
page += FPSTR(HTTP_FORM_OTHER3a);
for (byte i = 0; i < EMUL_MAX; i++) {
@@ -898,15 +905,7 @@ void HandleOtherConfiguration()
page.replace(F("{3"), (i == EMUL_NONE) ? F(D_NONE) : (i == EMUL_WEMO) ? F(D_BELKIN_WEMO) : F(D_HUE_BRIDGE));
page.replace(F("{4"), (i == EMUL_NONE) ? F("") : (i == EMUL_WEMO) ? F(" " D_SINGLE_DEVICE) : F(" " D_MULTI_DEVICE));
}
- page += F("
");
- uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present;
- for (byte i = 1; i < maxfn; i++) {
- page += FPSTR(HTTP_FORM_OTHER2);
- page.replace(F("{1"), String(i +1));
- snprintf_P(stemp, sizeof(stemp), PSTR(FRIENDLY_NAME"%d"), i +1);
- page.replace(F("{2"), stemp);
- page.replace(F("{3"), Settings.friendlyname[i]);
- }
+// page += F("
");
page += F("
");
#endif // USE_EMULATION
page += FPSTR(HTTP_FORM_END);
@@ -1079,7 +1078,7 @@ void HandleResetConfiguration()
return;
}
- char svalue[16];
+ char svalue[33];
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESET_CONFIGURATION);
@@ -1375,6 +1374,7 @@ void HandleHttpCommand()
} else {
message += F(D_NEED_USER_AND_PASSWORD "\"}");
}
+ SetHeader();
WebServer->send(200, FPSTR(HDR_CTYPE_JSON), message);
}
diff --git a/sonoff/xdrv_01_light.ino b/sonoff/xdrv_01_light.ino
index 44801bfc1..4ae7c1d09 100644
--- a/sonoff/xdrv_01_light.ino
+++ b/sonoff/xdrv_01_light.ino
@@ -188,7 +188,7 @@ void AriluxRfHandler()
AddLog(LOG_LEVEL_DEBUG);
if (hostcode == stored_hostcode) {
- char command[16];
+ char command[33];
char value = '-';
command[0] = '\0';
uint8_t keycode = arilux_rf_received_value & 0xFF;
@@ -533,7 +533,7 @@ void LightPowerOn()
void LightPreparePower()
{
char scolor[25];
- char scommand[16];
+ char scommand[33];
if (Settings.light_dimmer && !(light_power)) {
ExecuteCommandPower(devices_present, 7); // No publishPowerState
diff --git a/sonoff/xdrv_05_domoticz.ino b/sonoff/xdrv_05_domoticz.ino
index 745c42c7a..e989f9aff 100644
--- a/sonoff/xdrv_05_domoticz.ino
+++ b/sonoff/xdrv_05_domoticz.ino
@@ -224,7 +224,7 @@ boolean DomoticzCommand()
if (XdrvMailbox.payload >= 0) {
Settings.domoticz_switch_idx[XdrvMailbox.index -1] = XdrvMailbox.payload;
}
- snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DOMOTICZ_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.domoticz_key_idx[XdrvMailbox.index -1]);
+ snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DOMOTICZ_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.domoticz_switch_idx[XdrvMailbox.index -1]);
}
else if ((CMND_SENSORIDX == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= DZ_MAX_SENSORS)) {
if (XdrvMailbox.payload >= 0) {
@@ -398,6 +398,7 @@ void DomoticzSaveSettings()
ssensor_indices, Settings.domoticz_update_timer);
AddLog(LOG_LEVEL_INFO);
}
+#endif // USE_WEBSERVER
/*********************************************************************************************\
* Interface
@@ -431,5 +432,4 @@ boolean Xdrv05(byte function)
return result;
}
-#endif // USE_WEBSERVER
#endif // USE_DOMOTICZ
diff --git a/sonoff/xsns_04_snfsc.ino b/sonoff/xsns_04_snfsc.ino
index 67ee2d5ba..f8c9eeef0 100644
--- a/sonoff/xsns_04_snfsc.ino
+++ b/sonoff/xsns_04_snfsc.ino
@@ -105,7 +105,7 @@ void SonoffScSerialInput(char *rcvstat)
#ifdef USE_WEBSERVER
const char HTTP_SNS_SCPLUS[] PROGMEM =
- "%s{s}" D_LIGHT "{m}%d%{e}{s}" D_NOISE "{m}%d%{e}{s}" D_AIR_QUALITY "{m}%d%{e}"; // {s} = , {m} = | , {e} = |
+ "%s{s}" D_LIGHT "{m}%d%%{e}{s}" D_NOISE "{m}%d%%{e}{s}" D_AIR_QUALITY "{m}%d%%{e}"; // {s} = , {m} = | , {e} = |
#endif // USE_WEBSERVER
void SonoffScShow(boolean json)