diff --git a/README.md b/README.md index ac06b7364..b125eb803 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## Sonoff-Tasmota Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE. -Current version is **5.8.0** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. +Current version is **5.9.0** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. ### ATTENTION All versions diff --git a/platformio.ini b/platformio.ini index 5b7ed8a1c..0104c8342 100644 --- a/platformio.ini +++ b/platformio.ini @@ -13,10 +13,11 @@ src_dir = sonoff ; *** Uncomment one of the lines below to build/upload only one environment ;env_default = sonoff ;env_default = sonoff-NL +;env_default = sonoff-DE +;env_default = sonoff-PL ;env_default = sonoff-minimal ;env_default = sonoff-ds18x20 -; *** Sonoff et al [env:sonoff] platform = espressif8266 framework = arduino @@ -39,7 +40,6 @@ monitor_baud = 115200 ;upload_port = domus1:80/api/upload-arduino.php ;extra_scripts = pio/http-uploader.py -; *** Sonoff et al [env:sonoff-NL] platform = espressif8266 framework = arduino @@ -48,22 +48,23 @@ board_flash_mode = dout build_flags = -Wl,-Tesp8266.flash.1m0.ld -DMQTT_MAX_PACKET_SIZE=512 -DMY_LANGUAGE=nl-NL lib_deps = PubSubClient, NeoPixelBus, IRremoteESP8266, ArduinoJSON -; *** Serial Monitor options -monitor_baud = 115200 +[env:sonoff-DE] +platform = espressif8266 +framework = arduino +board = esp01_1m +board_flash_mode = dout +build_flags = -Wl,-Tesp8266.flash.1m0.ld -DMQTT_MAX_PACKET_SIZE=512 -DMY_LANGUAGE=de-DE +lib_deps = PubSubClient, NeoPixelBus, IRremoteESP8266, ArduinoJSON -; *** Upload Serial reset method for Wemos and NodeMCU -;upload_resetmethod = nodemcu +[env:sonoff-PL] +platform = espressif8266 +framework = arduino +board = esp01_1m +board_flash_mode = dout +build_flags = -Wl,-Tesp8266.flash.1m0.ld -DMQTT_MAX_PACKET_SIZE=512 -DMY_LANGUAGE=pl-PL +lib_deps = PubSubClient, NeoPixelBus, IRremoteESP8266, ArduinoJSON -; *** Upload file to OTA server using SCP -;upload_port = user@host:/path -;extra_scripts = pio/sftp-uploader.py - -; *** Upload file to OTA server using HTTP -;upload_port = domus1:80/api/upload-arduino.php -;extra_scripts = pio/http-uploader.py - -; Sonoff minimal -[env:sonoff-minimal] ; Placeholder to be configured +[env:sonoff-minimal] platform = espressif8266 framework = arduino board = esp01_1m @@ -71,21 +72,6 @@ board_flash_mode = dout build_flags = -Wl,-Tesp8266.flash.1m0.ld -DMQTT_MAX_PACKET_SIZE=512 -DBE_MINIMAL lib_deps = PubSubClient, NeoPixelBus, IRremoteESP8266, ArduinoJSON -; Serial Monitor options -monitor_baud = 115200 - -; *** Upload Serial reset method for Wemos and NodeMCU -;upload_resetmethod = nodemcu - -; *** Upload file to OTA server using SCP -;upload_port = user@host:/path -;extra_scripts = pio/sftp-uploader.py - -; *** Upload file to OTA server using HTTP -;upload_port = domus1:80/api/upload-arduino.php -;extra_scripts = pio/http-uploader.py - -; Sonoff multiple DS18x20 [env:sonoff-ds18x20] platform = espressif8266 framework = arduino @@ -93,17 +79,3 @@ board = esp01_1m board_flash_mode = dout build_flags = -Wl,-Tesp8266.flash.1m0.ld -DMQTT_MAX_PACKET_SIZE=707 -DUSE_DS18x20 -DMESSZ=600 lib_deps = PubSubClient, NeoPixelBus, IRremoteESP8266, ArduinoJSON, OneWire - -; Serial Monitor options -monitor_baud = 115200 - -; *** Upload Serial reset method for Wemos and NodeMCU -;upload_resetmethod = nodemcu - -; *** Upload file to OTA server using SCP -;upload_port = user@host:/path -;extra_scripts = pio/sftp-uploader.py - -; *** Upload file to OTA server using HTTP -;upload_port = domus1:80/api/upload-arduino.php -;extra_scripts = pio/http-uploader.py diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index fa341c4e9..9056069c4 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,80 @@ -/* 5.8.0 20170918 +/* 5.9.0 20171030 + * Rewrite code (partly) using Google C++ Style Guide (https://google.github.io/styleguide/cppguide.html) + * Rewrite code by using command lookup tables and javascript (client side) web page expansions + * Change HTML/CSS to enable nicer form field entry + * Change default PWM assignments for H801 RGB(CW) led controller to support optional Color/Dimmer control + * GPIO04 (W2) from GPIO_PWM2 to GPIO_USER to be user configurable for GPIO_PWM5 (second White - Warm if W1 is Cold) + * GPIO12 (Blue) GPIO_PWM3 no change + * GPIO13 (Green) from GPIO_PWM4 to GPIO_PWM2 + * GPIO14 (W1) from GPIO_PWM1 to GPIO_USER to be user configurable for GPIO_PWM4 (first White - Cold or Warm) + * GPIO15 (Red) from GPIO_PWM5 to GPIO_PWM1 + * Change default PWM assignments for MagicHome RGB(W) led controller to support optional Color/Dimmer control + * GPIO05 (Green) from GPIO_PWM4 to GPIO_PWM2 + * GPIO12 (Blue) from GPIO_PWM5 to GPIO_PWM3 + * GPIO13 (White) GPIO_USER to be user configurable for GPIO_PWM4 (White - Cold or Warm) + * GPIO14 (Red) from GPIO_PWM3 to GPIO_PWM1 + * Change default PWM assignment for Witty Cloud to support optional Color/Dimmer control (#976) + * GPIO12 (Green) from GPIO_PWM4 to GPIO_PWM2 + * GPIO13 (Blue) from GPIO_PWM5 to GPIO_PWM3 + * GPIO15 (Red) from GPIO_PWM3 to GPIO_PWM1 + * Change when another module is selected now all GPIO user configuration is removed + * Change command name IRRemote to IRSend (#956) + * Remove Arduino IDE version too low warning as it interferes with platformio.ini platform = espressif8266_stage + * Fix command FullTopic entry when using serial or console interface + * Fix possible UDP syslog blocking + * Fix minimum TelePeriod of 10 seconds set by web page + * Fix command GPIOx JSON response (#897) + * Fix inverted relay power on state (#909) + * Fix compile error when DOMOTICZ_UPDATE_TIMER is not defined (#930) + * Fix alignment of web page items in some browsers (#935) + * Fix setting all saved power settings to Off when SetOption0 (SaveState) = 0 (#955) + * Fix timezone range from -12/12 to -13/13 (#968) + * Fix Southern Hemisphere TIME_STD/TIME_DST (#968) + * Fix TLS MQTT SSL fingerprint test (#970, #808) + * Fix virtual relay status message used with Color/Dimmer control (#989) + * Fix command IRSend and IRHvac case sensitive parameter regression introduced with version 5.8.0 (#993) + * Fix pressure calculation for some BMP versions regression introduced with version 5.8.0i (#974) + * Fix Domoticz Dimmer set to same level not powering on (#945) + * Fix Blocked Loop when erasing large flash using command reset 2 (#1002) + * Fix relay power control when light power control is also configured as regression from 5.8.0 (#1016) + * Fix Mqtt server mDNS lookup only when MqttHost name is empty (#1026) + * Add debug information to MQTT subscribe + * Add translations to I2Cscan + * Add translation to BH1750 unit lx + * Add light scheme options (Color cycle Up, Down, Random) and moving WS2812 schemes up by 3 + * Add Domoticz counter sensor to IrReceive representing Received IR Protocol and Data + * Add option 0 to MqttHost to allow empty Mqtt host name + * Add support for Arilux AL-LC01 RGB Led controller (#370) + * Add esp8266 de-blocking to PubSubClient library (#790) + * Add Domoticz sensors for Voltage and Current (#903) + * Add platformio OTA upload support (#928, #934) + * Add warning to webpage when USE_MINIMAL is selected (#929) + * Add smoother movement of hour hand in WS2812 led clock (#936) + * Add support for Magic Home RGBW and some Arilux Led controllers (#940) + * Add command SetOption15 0 (default) for command PWM control or SetOption15 1 for commands Color/Dimmer control to PWM RGB(CW) leds (#941) + * Add Domoticz counter sensor to Sonoff Bridge representing Received RF code (#943) + * Add support for Luani HVIO board (https://luani.de/projekte/esp8266-hvio/) (#953) + * Add PWM initialization after restart (#955) + * Add IR Receiver support. Disable in user_config.h (#956) + * Add support for inverted PWM (#960) + * Add Sea level pressure calculation and Provide command Altitude (#974) + * Add support for up to 8 relays (#995) + * Add commands RfSync, RfLow, RfHigh, RfHost and RfCode to allow sending custom RF codes (#1001) + * Add retain to ENERGY messages controlled by command SensorRetain (#1013) + * Add commands Color2, Color3, Color4, Width2, Width3, Width4 and SetOption16 to set Ws2812 Clock parameters (#1019) + * Add German language file (#1022) + * Add support for connecting to MQTT brokers without userid and/or password (#1023) + * Add support for esp8266 core v2.4.0-rc2 (#1024) + * Add commands PwmRange 1,255..1023 and PwmFrequency 1,100..4000 (#1025) + * Add Polish language file (#1044, #1047) + * Add support for KMC 70011 Power Monitoring Smart Plug (#1045) + * Add support for VEML6070 I2C Ultra Violet level sensor (#1053) + * Add light turn Off Fade (#925) + * Add IrSend command option Panasonic as IrSend {"Protocol":"Panasonic", "Bits":16388, "Data":} + * where 16388 is 0x4004 hexadecimal (#1014) + * Add retry counter to DHT11/21/22 sensors (#1082) + * + * 5.8.0 20170918 * Remove the need for NeoPixelBus library for Hue support * Consolidate WS2812 into Sonoff Led for flexible future led strip library changes * Invert WS2812 fade speed to align with Sonoff led (Speed 1 = fast, Speed 8 = slow) @@ -934,7 +1010,7 @@ * Add reset 2 option erasing flash * Add status 5 option displaying network info * Add syslog check for Wifi connection - * Resize mqtt_publish log array + * Resize MqttPublish log array * Change Wifi smartconfig active from 100 to 60 seconds * Update Wifi initialization * diff --git a/sonoff/i18n.h b/sonoff/i18n.h index c49e31c8f..3269b3b40 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -17,6 +17,9 @@ along with this program. If not, see . */ +#ifndef _I18N_H_ +#define _I18N_H_ + #ifndef MY_LANGUAGE #include "language/en-GB.h" #else @@ -27,6 +30,56 @@ #endif // Common +enum UnitNames { + UNIT_AMPERE, + UNIT_HOUR, + UNIT_KILOWATTHOUR, + UNIT_LUX, + UNIT_MICROSECOND, + UNIT_MILLIAMPERE, + UNIT_MILLISECOND, + UNIT_MINUTE, + UNIT_PRESSURE, + UNIT_SECOND, + UNIT_SECTORS, + UNIT_VOLT, + UNIT_WATT, + UNIT_WATTHOUR }; +const char kUnitNames[] PROGMEM = + D_UNIT_AMPERE "|" + D_UNIT_HOUR "|" + D_UNIT_KILOWATTHOUR "|" + D_UNIT_LUX "|" + D_UNIT_MICROSECOND "|" + D_UNIT_MILLIAMPERE "|" + D_UNIT_MILLISECOND "|" + D_UNIT_MINUTE "|" + D_UNIT_PRESSURE "|" + D_UNIT_SECOND "|" + D_UNIT_SECTORS "|" + D_UNIT_VOLT "|" + D_UNIT_WATT "|" + D_UNIT_WATTHOUR ; + +const char S_JSON_COMMAND_NVALUE_SPACE_UNIT[] PROGMEM = "{\"%s\":\"%d %s\"}"; +const char S_JSON_COMMAND_SVALUE_SPACE_UNIT[] PROGMEM = "{\"%s\":\"%s %s\"}"; +const char S_JSON_COMMAND_NVALUE_UNIT[] PROGMEM = "{\"%s\":\"%d%s\"}"; +const char S_JSON_COMMAND_NVALUE_UNIT_NVALUE_UNIT[] PROGMEM = "{\"%s\":\"%d%s (%d%s)\"}"; + +const char S_JSON_COMMAND_NVALUE_SVALUE[] PROGMEM = "{\"%s\":\"%d (%s)\"}"; +const char S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE[] PROGMEM = "{\"%s\":\"%d (" D_ACTIVE " %d)\"}"; + +const char S_JSON_COMMAND_NVALUE[] PROGMEM = "{\"%s\":%d}"; +const char S_JSON_COMMAND_SVALUE[] PROGMEM = "{\"%s\":\"%s\"}"; +const char S_JSON_COMMAND_XVALUE[] PROGMEM = "{\"%s\":%s}"; // %s must provide quotes on non-number + +const char S_JSON_COMMAND_INDEX_NVALUE[] PROGMEM = "{\"%s%d\":%d}"; +const char S_JSON_COMMAND_INDEX_SVALUE[] PROGMEM = "{\"%s%d\":\"%s\"}"; +const char S_JSON_COMMAND_INDEX_SVALUE_SVALUE[] PROGMEM = "{\"%s%d\":\"%s%s\"}"; + +const char JSON_SNS_TEMPHUM[] PROGMEM = + "%s, \"%s\":{\"" D_TEMPERATURE "\":%s, \"" D_HUMIDITY "\":%s}"; + const char S_LOG_HTTP[] PROGMEM = D_LOG_HTTP; const char S_LOG_WIFI[] PROGMEM = D_LOG_WIFI; const char S_LOG_MQTT[] PROGMEM = D_LOG_MQTT; @@ -38,29 +91,26 @@ const char S_OFFLINE[] PROGMEM = D_OFFLINE; // sonoff.ino #define MAX_BUTTON_COMMANDS 5 // Max number of button commands supported -const char commands[MAX_BUTTON_COMMANDS][14] PROGMEM = { +const char kCommands[MAX_BUTTON_COMMANDS][14] PROGMEM = { D_CMND_WIFICONFIG " 1", // Press button three times D_CMND_WIFICONFIG " 2", // Press button four times D_CMND_WIFICONFIG " 3", // Press button five times D_CMND_RESTART " 1", // Press button six times D_CMND_UPGRADE " 1" }; // Press button seven times -const char wificfg[MAX_WIFI_OPTION][WCFG_MAX_STRING_LENGTH] PROGMEM = { +const char kWifiConfig[MAX_WIFI_OPTION][WCFG_MAX_STRING_LENGTH] PROGMEM = { D_WCFG_0_RESTART, D_WCFG_1_SMARTCONFIG, D_WCFG_2_WIFIMANAGER, D_WCFG_3_WPSCONFIG, D_WCFG_4_RETRY, D_WCFG_5_WAIT }; -const char PREFIXES[3][PRFX_MAX_STRING_LENGTH] PROGMEM = { +const char kPrefixes[3][PRFX_MAX_STRING_LENGTH] PROGMEM = { D_CMND, D_STAT, D_TELE }; -const char JSON_SNS_TEMPHUM[] PROGMEM = - "%s, \"%s\":{\"" D_TEMPERATURE "\":%s, \"" D_HUMIDITY "\":%s}"; - // support.ino -static const char monthNames[] = D_MONTH3LIST; +static const char kMonthNames[] = D_MONTH3LIST; // webserver.ino const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU; @@ -78,3 +128,5 @@ const char S_FIRMWARE_UPGRADE[] PROGMEM = D_FIRMWARE_UPGRADE; const char S_CONSOLE[] PROGMEM = D_CONSOLE; const char S_INFORMATION[] PROGMEM = D_INFORMATION; const char S_RESTART[] PROGMEM = D_RESTART; + +#endif // _I18N_H_ \ No newline at end of file diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h new file mode 100644 index 000000000..0574ab2e5 --- /dev/null +++ b/sonoff/language/de-DE.h @@ -0,0 +1,691 @@ +/* + de-DE.h - localization for German - Germany for Sonoff-Tasmota + + Copyright (C) 2017 VinceMasuka + + 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_DE_DE_H_ +#define _LANGUAGE_DE_DE_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 "SonMonDieMitDonFriSam" +#define D_MONTH3LIST "JanFebMaeAprMaiJunJulAugSepOktNovDez" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ABORTED "abgebrochen" +#define D_ACTIVE "aktiv" +#define D_ADDRESS "Addresse" +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Ausschlagsqualität" +#define D_AIRQUALITY "AusschlagsQualität" +#define D_AP "AP" // Access Point +#define D_APMAC_ADDRESS "APMac" +#define D_APPENDED "angehängt" +#define D_AS "wie" +#define D_AUTO "AUTO" +#define D_BAUDRATE "Baudrate" +#define D_BLINK "Blinken" +#define D_BLINKOFF "BlinkenAus" +#define D_BOOTVERSION "Boot" +#define D_BOOT_COUNT "Boot-Zähler" +#define D_BOOTCOUNT "BootZähler" +#define D_BRIGHTLIGHT "hell" +#define D_BUILDDATETIME "BuildDatumUhrzeit" +#define D_BUTTON "Taste" +#define D_CELSIUS "Celsius" +#define D_CODE "code" // Button code +#define D_COLDLIGHT "kalt" +#define D_COMMAND "Befehl" +#define D_CONNECTED "verbunden" +#define D_COREVERSION "Kern" +#define D_COUNT "zählen" +#define D_COUNTER "Zähler" +#define D_CURRENT "Strom" // As in Voltage and Current +#define D_DATA "Daten" +#define D_DARKLIGHT "dunkel" +#define D_DEBUG "debug" +#define D_DISABLED "deaktiviert" +#define D_DNS_SERVER "DNS Server" +#define D_DNSSERVER "DNSServer" +#define D_DONE "erledigt" +#define D_DST_TIME "DST" +#define D_EMPTY "leer" +#define D_EMULATION "Emulierung" +#define D_ENABLED "aktiviert" +#define D_ENDDST "EndDST" // End Daylight Savings Time +#define D_ERASE "löschen" +#define D_ERROR "Fehler" +#define D_EVERY "alle" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "fehlgeschlagen" +#define D_FALLBACK "Rückgriff" +#define D_FALLBACK_TOPIC "Rückgriff topic" +#define D_FALLBACKTOPIC "RückgriffTopic" +#define D_FALSE "falsch" +#define D_FILE "Datei" +#define D_FLASHMODE "FlashMode" +#define D_FLASHSIZE "FlashSize" +#define D_FREE_MEMORY "freier Speicher" +#define D_FREEMEMORY "frei" +#define D_FROM "von" +#define D_GATEWAY "Gateway" +#define D_GROUP "Gruppe" +#define D_HEAPSIZE "Heap-Größe" +#define D_HIGH "hoch" +#define D_HOST "host" +#define D_HOSTNAME "Hostname" +#define D_HUMIDITY "Feuchtigkeit" +#define D_ILLUMINANCE "Beleuchtungsintensität" +#define D_IMMEDIATE "direkt" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Info" +#define D_INITIALIZED "initialisiert" +#define D_IP_ADDRESS "IP-Addresse" +#define D_LIGHT "Licht" +#define D_LOCAL_TIME "örtlich" +#define D_LOW "niedrig" +#define D_LWT "LWT" +#define D_MAC "Mac" +#define D_MASK "Maske" +#define D_MODULE "Modul" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "Mehrfachdruck" +#define D_NO "nein" +#define D_NOISE "Lautstärke" +#define D_NONE "keine" +#define D_OFF "aus" +#define D_OFFLINE "offline" +#define D_OK "OK" +#define D_ON "an" +#define D_ONLINE "online" +#define D_OR "oder" +#define D_PASSWORD "Passwort" +#define D_PERIOD "Punkt" +#define D_PORT "port" +#define D_POWER_FACTOR "Leistungsfaktor" +#define D_POWERFACTOR "Faktor" +#define D_POWERUSAGE "Leistung" +#define D_PRESSURE "Druck" +#define D_PRESSUREATSEALEVEL "MeeresDruck" +#define D_PROGRAM_FLASH_SIZE "Programm-Flash-Größe" +#define D_PROGRAMFLASHSIZE "ProgramFlashSize" +#define D_PROGRAM_SIZE "Programmgröße" +#define D_PROGRAMSIZE "ProgramSize" +#define D_PROJECT "Projekt" +#define D_RECEIVED "erhalten" +#define D_RESTART "Neustart" +#define D_RESTARTING "starte neu" +#define D_RESTART_REASON "Grund für Neustart" +#define D_RESTARTREASON "RestartReason" +#define D_RESTORE "wiederherstellen" +#define D_RETAINED "beibehalten" +#define D_SAVE "speichern" +#define D_SAVEADDRESS "SaveAddress" +#define D_SAVECOUNT "SaveCount" +#define D_SAVESTATE "SaveState" +#define D_SDKVERSION "SDK" +#define D_SELECTED "ausgewählt" +#define D_SENSOR "Sensor" +#define D_SERIAL "Serial" +#define D_BYTES "Bytes" +#define D_SSID "SSID" +#define D_START "Start" +#define D_STARTED "gestartet" +#define D_STARTDST "StartDST" // Start Daylight Savings Time +#define D_STD_TIME "STD" +#define D_STOP "stopp" +#define D_SUBNET_MASK "Subnetzmaske" +#define D_SUBNETMASK "Subnetmaske" +#define D_SUBSCRIBE_TO "subscribe to" +#define D_SUCCESSFUL "erfolgreich" +#define D_SWITCH "switch" +#define D_SYNC "sync" +#define D_SYS "sys" // Sys log +#define D_TEMPERATURE "Temperatur" +#define D_TEMPERATURE_UNIT "TempUnit" +#define D_TIME "Zeit" +#define D_TO "bis" +#define D_TODAY "heute" +#define D_TOGGLE "schalten" +#define D_TOPIC "topic" +#define D_TOTAL "Total" +#define D_TRANSMIT "Übertragen" +#define D_TRUE "wahr" +#define D_TYPE "Typ" +#define D_UNKNOWN "unbekannt" +#define D_UPGRADE "upgrade" +#define D_UPLOAD "upload" +#define D_UPTIME "Laufzeit" +#define D_USER "Benutzer" +#define D_UTC_TIME "UTC" +#define D_UV_LEVEL "UV Level" +#define D_VCC "VCC" +#define D_VERSION "Version" +#define D_VOLTAGE "Spannung" +#define D_WARMLIGHT "warm" +#define D_WEB "web" // Web log +#define D_WEB_SERVER "Web-Server" +#define D_WIFI "WLAN" +#define D_WRONG "falsch" +#define D_YESTERDAY "gestern" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "in flash gespeichert am" +#define D_LOADED_FROM_FLASH_AT "geladen aus flash am" +#define D_USE_DEFAULTS "Standard verwenden" +#define D_ERASED_SECTOR "gelöschter Sektor" + +// sonoff.ino +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "serielles logging deaktiviert" +#define D_SYSLOG_LOGGING_REENABLED "syslog logging reaktiviert" + +#define D_SET_BAUDRATE_TO "Baudrate eingestell auf" +#define D_RECEIVED_TOPIC "erhaltenes topic" +#define D_DATA_SIZE "Datengröße" +#define D_ANALOG_INPUT0 "Analog0" + +#define D_FINGERPRINT "TLS-Fingerabdruck wird verifiziert..." +#define D_TLS_CONNECT_FAILED_TO "TLS-Verbindung fehlgeschlagen an" +#define D_RETRY_IN "Wiederversuch in" +#define D_VERIFIED "verifiziert" +#define D_INSECURE "unsichere Verbindung aufgrund ungültigen Fingerabdrucks" +#define D_CONNECT_FAILED_TO "Verbindung fehlgeschlagen aufgrund von" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blocked Loop" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig fehlgeschlagen mit Status" +#define D_ACTIVE_FOR_1_MINUTE "aktiv für 1 Minute" +#define D_FAILED_TO_START "Starten fehlgeschlagen" +#define D_PATCH_ISSUE_2186 "Patch-Problem 2186" +#define D_CONNECTING_TO_AP "verbinden mit AP" +#define D_IN_MODE "in Modus" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Verbindung fehlgeschlagen da keine IP-Adresse erhalten wurde" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Verbindung fehlgeschlagen da AP nicht erreicht werden konnte" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Verbindung fehlgeschlagen mit AP falschem Passwort" +#define D_CONNECT_FAILED_AP_TIMEOUT "Verbindung fehlgeschlagen mit AP timeout" +#define D_ATTEMPTING_CONNECTION "Verbindungsversuch..." +#define D_CHECKING_CONNECTION "prüfe Verbindung..." +#define D_QUERY_DONE "Suchanfrage abgeschlossen. MQTT-Services gefunden" +#define D_MQTT_SERVICE_FOUND "MQTT-Service gefunden bei" +#define D_I2CSCAN_DEVICES_FOUND_AT "Gerät(e) gefunden bei" +#define D_FOUND_AT "gefunden bei" +#define D_I2CSCAN_UNKNOWN_ERROR_AT "unbekannter Fehler bei" +#define D_I2CSCAN_NO_DEVICES_FOUND "keine Geräte gefunden" +#define D_SYSLOG_HOST_NOT_FOUND "syslog host nicht gefunden" + +// webserver.ino +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMUM-Firmware - bitte upgraden" +#define D_WEBSERVER_ACTIVE_ON "Web-Server aktiv bei" +#define D_WITH_IP_ADDRESS "mit IP-Adresse" +#define D_WEBSERVER_STOPPED "Web-Server angehalten" +#define D_FILE_NOT_FOUND "Datei nicht gefunden" +#define D_REDIRECTED "umgeleitet zu captive portal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "WLAN-Manager AccessPoint gesetzt und behält Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "WLAN-Manager AccessPoint gesetzt" +#define D_TRYING_TO_CONNECT "versuche Gerät mit Netzwerk zu verbinden" + +#define D_RESTART_IN "Neustart in" +#define D_SECONDS "Sekunden" +#define D_DEVICE_WILL_RESTART "Gerät wird in wenigen Sekunden neu starten" +#define D_BUTTON_TOGGLE "schalten" +#define D_CONFIGURATION "Einstellungen" +#define D_INFORMATION "Informationen" +#define D_FIRMWARE_UPGRADE "Firmware-Upgrade" +#define D_CONSOLE "Konsole" +#define D_CONFIRM_RESTART "Neustart bestätigen" + +#define D_CONFIGURE_MODULE "Modul konfigurieren" +#define D_CONFIGURE_WIFI "WLAN konfigurieren" +#define D_CONFIGURE_MQTT "MQTT konfigurieren" +#define D_CONFIGURE_DOMOTICZ "Domoticz konfigurieren" +#define D_CONFIGURE_LOGGING "Logging konfigurieren" +#define D_CONFIGURE_OTHER "Sonstige Konfiguration" +#define D_CONFIRM_RESET_CONFIGURATION "Zurücksetzen der Konfiguration bestätigen" +#define D_RESET_CONFIGURATION "Konfiguration zurücksetzen" +#define D_BACKUP_CONFIGURATION "Konfiguration sichern" +#define D_RESTORE_CONFIGURATION "Konfiguration wiederherstellen" +#define D_MAIN_MENU "Hauptmenü" + +#define D_MODULE_PARAMETERS "Modul-Parameter" +#define D_MODULE_TYPE "Module-Typ" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "serieller Eingang [serial in]" +#define D_SERIAL_OUT "serieller Ausgang [serial out]" + +#define D_WIFI_PARAMETERS "WLAN-Parameter" +#define D_SCAN_FOR_WIFI_NETWORKS "Suche nach WLAN-Netzwerke" +#define D_SCAN_DONE "scan abgeschlossen" +#define D_NO_NETWORKS_FOUND "keine Netzwerke gefunden" +#define D_REFRESH_TO_SCAN_AGAIN "Aktualisieren um erneut zu suchen" +#define D_DUPLICATE_ACCESSPOINT "AccessPoint duplizieren" +#define D_SKIPPING_LOW_QUALITY "überspringe wegen niedriger Qualität" +#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 "AP1 Password" +#define D_AP2_SSID "AP2 SSID" +#define D_AP2_PASSWORD "AP2 Password" + +#define D_MQTT_PARAMETERS "MQTT-Parameter" +#define D_CLIENT "client" +#define D_FULL_TOPIC "full topic" + +#define D_LOGGING_PARAMETERS "Logging-Parameter" +#define D_LOG_LEVEL "log level" +#define D_MORE_DEBUG "More debug" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog port" +#define D_TELEMETRY_PERIOD "Telemetry period" + +#define D_OTHER_PARAMETERS "andere Parameter" +#define D_WEB_ADMIN_PASSWORD "Web-Admin-Passwort" +#define D_MQTT_ENABLE "MQTT aktivieren" +#define D_FRIENDLY_NAME "Name [friendly name]" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "einzelnes Gerät" +#define D_MULTI_DEVICE "Mehrfachgerät" + +#define D_SAVE_CONFIGURATION "Konfiguration speichern" +#define D_CONFIGURATION_SAVED "Konfiguration gespeichert" +#define D_CONFIGURATION_RESET "Konfiguration zurücksetzen" + +#define D_PROGRAM_VERSION "Programmversion" +#define D_BUILD_DATE_AND_TIME "Build-Datum & -Uhrzeit" +#define D_CORE_AND_SDK_VERSION "Core-/SDK-Version" +#define D_FLASH_WRITE_COUNT "Flash-Schreibzähler" +#define D_MAC_ADDRESS "MAC-Adresse" +#define D_MQTT_HOST "MQTT host" +#define D_MQTT_PORT "MQTT port" +#define D_MQTT_CLIENT "MQTT client" +#define D_MQTT_USER "MQTT-Benutzer" +#define D_MQTT_TOPIC "MQTT topic" +#define D_MQTT_GROUP_TOPIC "MQTT group topic" +#define D_MQTT_FULL_TOPIC "MQTT full topic" +#define D_MDNS_DISCOVERY "mDNS-Ermittlung" +#define D_MDNS_ADVERTISE "mDNS-Bekanntmachung" +#define D_ESP_CHIP_ID "ESP Chip ID" +#define D_FLASH_CHIP_ID "Flash Chip ID" +#define D_FLASH_CHIP_SIZE "Flash-Größe" +#define D_FREE_PROGRAM_SPACE "freier Programmspeicherplatz" + +#define D_UPGRADE_BY_WEBSERVER "Upgrade über Web-Server" +#define D_OTA_URL "OTA-URL" +#define D_START_UPGRADE "Upgrade starten" +#define D_UPGRADE_BY_FILE_UPLOAD "Upgrade per Datei-Upload" +#define D_UPLOAD_STARTED "Upload gestartet" +#define D_UPGRADE_STARTED "Upgrade gestartet" +#define D_UPLOAD_DONE "Upload abgeschlossen" +#define D_UPLOAD_ERR_1 "keine Datei ausgewählt" +#define D_UPLOAD_ERR_2 "ungenügend Speicherplatz" +#define D_UPLOAD_ERR_3 "magic byte ist nicht 0xE9" +#define D_UPLOAD_ERR_4 "Flash-Größe des Programmes ist größer als die reale Flash-Größe" +#define D_UPLOAD_ERR_5 "Upload-buffer-Vergleich weicht ab" +#define D_UPLOAD_ERR_6 "Upload fehlgeschlagen. Aktiviere logging 3" +#define D_UPLOAD_ERR_7 "Upload abgebrochen" +#define D_UPLOAD_ERR_8 "Datei ungültig" +#define D_UPLOAD_ERR_9 "Datei zu groß" +#define D_UPLOAD_ERROR_CODE "Upload-Fehler-Code" + +#define D_ENTER_COMMAND "Befehl eingeben" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "aktivere weblog 2 falls Reaktion erwartet" +#define D_NEED_USER_AND_PASSWORD "Benutzer benötigt=&password=" + +// xdrv_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz parameters" +#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_UPDATE_TIMER "Update timer" + +// xdrv_ir-send.ino +#define D_INVALID_JSON "ungültiger JSON" +#define D_PROTOCOL_NOT_SUPPORTED "Protokoll nicht unterstützt" +#define D_IR_PROTOCOL "PROTOKOLL" +#define D_IR_BITS "BITS" +#define D_IR_DATA "DATEN" +#define D_IRHVAC_VENDOR "HERSTELLER" +#define D_IRHVAC_POWER "STROM" +#define D_IRHVAC_MODE "MODUS" +#define D_IRHVAC_FANSPEED "LÜFTERGESCHWINDIGKEIT" +#define D_IRHVAC_TEMP "TEMPERATUR" +#define D_IRRECEIVED "IrReceived" + +// xdrv_snfbridge.ino +#define D_RFRECEIVED "RfReceived" +#define D_START_LEARNING "starte Anlernen" +#define D_SET_TO_DEFAULT "auf Standard zurücksetzen" +#define D_DEFAULT_SENT "Standard gesendet" +#define D_LEARNED_SENT "Anlernen gesendet" +#define D_LEARNING_ACTIVE "Anlernen aktiv" +#define D_LEARN_FAILED "Anlernen fehlgeschlagen" +#define D_LEARNED "angelernt" +#define D_SAVED "gespeichert" + +// xdrv_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast deaktiviert" +#define D_MULTICAST_REJOINED "Multicast (wieder-)verbunden" +#define D_MULTICAST_JOIN_FAILED "Multicast-Verbinden fehlgeschlagen" +#define D_FAILED_TO_SEND_RESPONSE "Antwort senden fehlgeschlagen" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basic event" +#define D_WEMO_EVENT_SERVICE "WeMo event service" +#define D_WEMO_SETUP "WeMo-Setup" +#define D_RESPONSE_SENT "Antwort gesendet" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue-Setup" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API nicht implementiert" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 Antwortpakete gesendet" + +// xsns_dht.ino +#define D_TIMEOUT_WAITING_FOR "Timeout wartet auf" +#define D_START_SIGNAL_LOW "Startausschlag niedrig" +#define D_START_SIGNAL_HIGH "Startausschlag hoch" +#define D_PULSE "pulse" +#define D_CHECKSUM_FAILURE "Checksum-Fehler" + +// xsns_ds18b20.ino +#define D_SENSOR_BUSY "Sensor beschäftigt" +#define D_SENSOR_CRC_ERROR "Sensor CRC-Fehler" + +// xsns_hlw8012.ino +#define D_MAXPOWERREACHED "MaxPowerReached" +#define D_MAXPOWERREACHEDRETRY "MaxPowerReachedRetry" +#define D_POWERMONITOR "PowerMonitor" +#define D_ENERGYMONITOR "EnergyMonitor" +#define D_MAXENERGYREACHED "MaxEnergyReached" +#define D_ENERGY_TODAY "Energie heute" +#define D_ENERGY_YESTERDAY "Energie gestern" +#define D_ENERGY_TOTAL "Energie insgesamt" + +// xsns_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor hat ACK-Befehl nicht ausgeführt" +#define D_SHT1X_FOUND "SHT1X gefunden" + +// 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_DHT22 "DHT22" +#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_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_BACKLIGHT "BLight" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_HOUR "h" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "min" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "Sektoren" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" + +// Log message prefix +#define D_LOG_APPLICATION "APP: " +#define D_LOG_BRIDGE "BRG: " +#define D_LOG_CONFIG "CFG: " +#define D_LOG_COMMAND "CMD: " +#define D_LOG_DHT "DHT: " +#define D_LOG_DOMOTICZ "DOM: " +#define D_LOG_DSB "DSB: " +#define D_LOG_HTTP "HTP: " +#define D_LOG_I2C "I2C: " +#define D_LOG_IRR "IRR: " +#define D_LOG_LOG "LOG: " +#define D_LOG_MODULE "MOD: " +#define D_LOG_MDNS "DNS: " +#define D_LOG_MQTT "MQT: " +#define D_LOG_OTHER "OTH: " +#define D_LOG_RESULT "RSL: " +#define D_LOG_SERIAL "SER: " +#define D_LOG_SHT1 "SHT: " +#define D_LOG_UPLOAD "UPL: " +#define D_LOG_UPNP "UPP: " +#define D_LOG_WIFI "WIF: " + +// Result +#define D_RSLT_RESULT "ERGEBNIS" +#define D_RSLT_INFO "INFO" +#define D_RSLT_STATE "STATUS" +#define D_RSLT_SENSOR "SENSOR" +#define D_RSLT_UPTIME "LAUFZEIT" +#define D_RSLT_MARGINS "TOLERANZ" +#define D_RSLT_WARNING "WARNUNG" +#define D_RSLT_ENERGY "ENERGIE" + +// Commands +#define D_CMND_MQTTHOST "MqttHost" +#define D_CMND_MQTTPORT "MqttPort" +#define D_CMND_MQTTRETRY "MqttRetry" +#define D_CMND_STATETEXT "StateText" +#define D_CMND_MQTTFINGERPRINT "MqttFingerprint" +#define D_CMND_MQTTCLIENT "MqttClient" +#define D_CMND_MQTTUSER "MqttUser" +#define D_CMND_MQTTPASSWORD "MqttPassword" +#define D_CMND_FULLTOPIC "FullTopic" +#define D_CMND_PREFIX "Prefix" + #define PRFX_MAX_STRING_LENGTH 5 + #define D_CMND "cmnd" + #define D_STAT "stat" + #define D_TELE "tele" +#define D_CMND_GROUPTOPIC "GroupTopic" +#define D_CMND_TOPIC "Topic" +#define D_CMND_BUTTONTOPIC "ButtonTopic" +#define D_CMND_SWITCHTOPIC "SwitchTopic" +#define D_CMND_BUTTONRETAIN "ButtonRetain" +#define D_CMND_SWITCHRETAIN "SwitchRetain" +#define D_CMND_POWERRETAIN "PowerRetain" +#define D_CMND_SENSORRETAIN "SensorRetain" +#define D_CMND_BACKLOG "Backlog" +#define D_CMND_DELAY "Delay" +#define D_CMND_STATUS "Status" + #define D_STATUS1_PARAMETER "PRM" + #define D_STATUS2_FIRMWARE "FWR" + #define D_STATUS3_LOGGING "LOG" + #define D_STATUS4_MEMORY "MEM" + #define D_STATUS5_NETWORK "NET" + #define D_STATUS6_MQTT "MQT" + #define D_STATUS7_TIME "TIM" + #define D_STATUS8_POWER "PWR" + #define D_STATUS9_MARGIN "PTH" + #define D_STATUS10_SENSOR "SNS" + #define D_STATUS11_STATUS "STS" +#define D_CMND_POWER "Power" + #define D_RSLT_POWER "POWER" +#define D_CMND_POWERONSTATE "PowerOnState" +#define D_CMND_PULSETIME "PulseTime" +#define D_CMND_BLINKTIME "BlinkTime" +#define D_CMND_BLINKCOUNT "BlinkCount" +#define D_CMND_SAVEDATA "SaveData" +#define D_CMND_SETOPTION "SetOption" +#define D_CMND_TEMPERATURE_RESOLUTION "TempRes" +#define D_CMND_HUMIDITY_RESOLUTION "HumRes" +#define D_CMND_PRESSURE_RESOLUTION "PressRes" +#define D_CMND_POWER_RESOLUTION "WattRes" +#define D_CMND_VOLTAGE_RESOLUTION "VoltRes" +#define D_CMND_ENERGY_RESOLUTION "EnergyRes" +#define D_CMND_MODULE "Module" +#define D_CMND_MODULES "Modules" +#define D_CMND_GPIO "GPIO" + #define D_NOT_SUPPORTED "Not supported" +#define D_CMND_GPIOS "GPIOs" +#define D_CMND_PWM "PWM" +#define D_CMND_PWMFREQUENCY "PWMFrequency" +#define D_CMND_PWMRANGE "PWMRange" +#define D_CMND_COUNTER "Counter" +#define D_CMND_COUNTERTYPE "CounterType" +#define D_CMND_COUNTERDEBOUNCE "CounterDebounce" +#define D_CMND_SLEEP "Sleep" +#define D_CMND_UPLOAD "Upload" +#define D_CMND_UPGRADE "Upgrade" + #define D_ONE_OR_GT "1 or >%s to upgrade" +#define D_CMND_OTAURL "OtaUrl" +#define D_CMND_SERIALLOG "SerialLog" +#define D_CMND_SYSLOG "SysLog" +#define D_CMND_LOGHOST "LogHost" +#define D_CMND_LOGPORT "LogPort" +#define D_CMND_IPADDRESS "IPAddress" +#define D_CMND_NTPSERVER "NtpServer" +#define D_CMND_AP "Ap" +#define D_CMND_SSID "SSId" +#define D_CMND_PASSWORD "Password" +#define D_CMND_HOSTNAME "Hostname" +#define D_CMND_WIFICONFIG "WifiConfig" + #define WCFG_MAX_STRING_LENGTH 12 + #define D_WCFG_0_RESTART "Restart" + #define D_WCFG_1_SMARTCONFIG "SmartConfig" + #define D_WCFG_2_WIFIMANAGER "WifiManager" + #define D_WCFG_3_WPSCONFIG "WPSConfig" + #define D_WCFG_4_RETRY "Retry" + #define D_WCFG_5_WAIT "Wait" +#define D_CMND_FRIENDLYNAME "FriendlyName" +#define D_CMND_SWITCHMODE "SwitchMode" +#define D_CMND_WEBSERVER "Webserver" + #define D_WEBSERVER_MODE "WebServerMode" + #define D_ACTIVE_FOR "Active for" + #define D_ON_DEVICE "on" +#define D_CMND_WEBPASSWORD "WebPassword" +#define D_CMND_WEBLOG "WebLog" +#define D_CMND_EMULATION "Emulation" +#define D_CMND_TELEPERIOD "TelePeriod" +#define D_CMND_RESTART "Restart" + #define D_ONE_TO_RESTART "1 to restart" +#define D_CMND_RESET "Reset" + #define D_RESET_AND_RESTARTING "Reset and Restarting" + #define D_ONE_TO_RESET "1 to reset" +#define D_CMND_TIMEZONE "Timezone" +#define D_CMND_ALTITUDE "Altitude" +#define D_CMND_LEDPOWER "LedPower" +#define D_CMND_LEDSTATE "LedState" +#define D_CMND_CFGDUMP "CfgDump" +#define D_CMND_I2CSCAN "I2CScan" +#define D_CMND_EXCEPTION "Exception" + +// Commands xdrv_domoticz.ino +#define D_CMND_DOMOTICZ "Domoticz" +#define D_CMND_IDX "Idx" +#define D_CMND_KEYIDX "KeyIdx" +#define D_CMND_SWITCHIDX "SwitchIdx" +#define D_CMND_SENSORIDX "SensorIdx" +#define D_CMND_UPDATETIMER "UpdateTimer" + +// Commands xdrv_ir_send.ino +#define D_CMND_IRSEND "IRSend" +#define D_CMND_IRHVAC "IRHVAC" + +// Commands xdrv_snfbridge.ino +#define D_CMND_RFCODE "RfCode" +#define D_CMND_RFHIGH "RfHigh" +#define D_CMND_RFHOST "RfHost" +#define D_CMND_RFKEY "RfKey" +#define D_CMND_RFLOW "RfLow" +#define D_CMND_RFSYNC "RfSync" + +// Commands xdrv_snfled.ino +#define D_CMND_COLOR "Color" +#define D_CMND_COLORTEMPERATURE "CT" +#define D_CMND_DIMMER "Dimmer" +#define D_CMND_LED "Led" +#define D_CMND_LEDTABLE "LedTable" +#define D_CMND_FADE "Fade" +#define D_CMND_PIXELS "Pixels" +#define D_CMND_SCHEME "Scheme" +#define D_CMND_SPEED "Speed" +#define D_CMND_WAKEUP "Wakeup" +#define D_CMND_WAKEUPDURATION "WakeUpDuration" +#define D_CMND_WIDTH "Width" + +// Commands xsns_hlw8012.ino +#define D_CMND_POWERLOW "PowerLow" +#define D_CMND_POWERHIGH "PowerHigh" +#define D_CMND_VOLTAGELOW "VoltageLow" +#define D_CMND_VOLTAGEHIGH "VoltageHigh" +#define D_CMND_CURRENTLOW "CurrentLow" +#define D_CMND_CURRENTHIGH "CurrentHigh" +#define D_CMND_ENERGYRESET "EnergyReset" +#define D_CMND_HLWPCAL "HlwPcal" +#define D_CMND_HLWPSET "HlwPset" +#define D_CMND_HLWUCAL "HlwUcal" +#define D_CMND_HLWUSET "HlwUset" +#define D_CMND_HLWICAL "HlwIcal" +#define D_CMND_HLWISET "HlwIset" +#define D_CMND_MAXPOWER "MaxPower" +#define D_CMND_MAXPOWERHOLD "MaxPowerHold" +#define D_CMND_MAXPOWERWINDOW "MaxPowerWindow" +#define D_CMND_SAFEPOWER "SafePower" +#define D_CMND_SAFEPOWERHOLD "SafePowerHold" +#define D_CMND_SAFEPOWERWINDOW "SafePowerWindow" +#define D_CMND_MAXENERGY "MaxEnergy" +#define D_CMND_MAXENERGYSTART "MaxEnergyStart" + +#endif // _LANGUAGE_DE_DE_H_ \ No newline at end of file diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index d5acc0fc0..a621ae753 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -17,9 +17,13 @@ along with this program. If not, see . */ +#ifndef _LANGUAGE_EN_GB_H_ +#define _LANGUAGE_EN_GB_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. @@ -134,6 +138,7 @@ #define D_POWERFACTOR "Factor" #define D_POWERUSAGE "Power" #define D_PRESSURE "Pressure" +#define D_PRESSUREATSEALEVEL "SeaPressure" #define D_PROGRAM_FLASH_SIZE "Program Flash Size" #define D_PROGRAMFLASHSIZE "ProgramFlashSize" #define D_PROGRAM_SIZE "Program Size" @@ -163,6 +168,7 @@ #define D_STOP "Stop" #define D_SUBNET_MASK "Subnet Mask" #define D_SUBNETMASK "Subnetmask" +#define D_SUBSCRIBE_TO "Subscribe to" #define D_SUCCESSFUL "Successful" #define D_SWITCH "Switch" #define D_SYNC "Sync" @@ -182,8 +188,9 @@ #define D_UPGRADE "upgrade" #define D_UPLOAD "Upload" #define D_UPTIME "Uptime" -#define D_UTC_TIME "UTC" #define D_USER "User" +#define D_UTC_TIME "UTC" +#define D_UV_LEVEL "UV Level" #define D_VCC "Vcc" #define D_VERSION "Version" #define D_VOLTAGE "Voltage" @@ -242,6 +249,7 @@ #define D_SYSLOG_HOST_NOT_FOUND "Syslog Host not found" // webserver.ino +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - please upgrade" #define D_WEBSERVER_ACTIVE_ON "Web server active on" #define D_WITH_IP_ADDRESS "with IP address" #define D_WEBSERVER_STOPPED "Web server stopped" @@ -366,27 +374,28 @@ #define D_DOMOTICZ_KEY_IDX "Key idx" #define D_DOMOTICZ_SWITCH_IDX "Switch idx" #define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define DOMOTICZ_SENSORS_MAX_STRING_LENGTH 14 #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_UPDATE_TIMER "Update timer" -#define D_CONFIGURE_DOMOTICZ "Configure Domoticz" // xdrv_ir-send.ino #define D_INVALID_JSON "Invalid JSON" #define D_PROTOCOL_NOT_SUPPORTED "Protocol not supported" -#define D_IRSEND_PROTOCOL "PROTOCOL" -#define D_IRSEND_BITS "BITS" -#define D_IRSEND_DATA "DATA" +#define D_IR_PROTOCOL "PROTOCOL" +#define D_IR_BITS "BITS" +#define D_IR_DATA "DATA" #define D_IRHVAC_VENDOR "VENDOR" #define D_IRHVAC_POWER "POWER" #define D_IRHVAC_MODE "MODE" #define D_IRHVAC_FANSPEED "FANSPEED" #define D_IRHVAC_TEMP "TEMP" +#define D_IRRECEIVED "IrReceived" // xdrv_snfbridge.ino #define D_RFRECEIVED "RfReceived" @@ -397,6 +406,7 @@ #define D_LEARNING_ACTIVE "Learning active" #define D_LEARN_FAILED "Learn failed" #define D_LEARNED "Learned" +#define D_SAVED "Saved" // xdrv_wemohue.ino #define D_MULTICAST_DISABLED "Multicast disabled" @@ -452,18 +462,23 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_IRREMOTE "IRremote" +#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_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_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_BACKLIGHT "BLight" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_HOUR "Hr" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" #define D_UNIT_MICROSECOND "us" #define D_UNIT_MILLIAMPERE "mA" #define D_UNIT_MILLISECOND "ms" @@ -485,17 +500,18 @@ #define D_LOG_DSB "DSB: " #define D_LOG_HTTP "HTP: " #define D_LOG_I2C "I2C: " +#define D_LOG_IRR "IRR: " #define D_LOG_LOG "LOG: " #define D_LOG_MODULE "MOD: " #define D_LOG_MDNS "DNS: " #define D_LOG_MQTT "MQT: " #define D_LOG_OTHER "OTH: " #define D_LOG_RESULT "RSL: " +#define D_LOG_SERIAL "SER: " #define D_LOG_SHT1 "SHT: " #define D_LOG_UPLOAD "UPL: " #define D_LOG_UPNP "UPP: " #define D_LOG_WIFI "WIF: " -#define D_LOG_SERIAL "SER: " // Result #define D_RSLT_RESULT "RESULT" @@ -564,6 +580,8 @@ #define D_NOT_SUPPORTED "Not supported" #define D_CMND_GPIOS "GPIOs" #define D_CMND_PWM "PWM" +#define D_CMND_PWMFREQUENCY "PWMFrequency" +#define D_CMND_PWMRANGE "PWMRange" #define D_CMND_COUNTER "Counter" #define D_CMND_COUNTERTYPE "CounterType" #define D_CMND_COUNTERDEBOUNCE "CounterDebounce" @@ -606,6 +624,7 @@ #define D_RESET_AND_RESTARTING "Reset and Restarting" #define D_ONE_TO_RESET "1 to reset" #define D_CMND_TIMEZONE "Timezone" +#define D_CMND_ALTITUDE "Altitude" #define D_CMND_LEDPOWER "LedPower" #define D_CMND_LEDSTATE "LedState" #define D_CMND_CFGDUMP "CfgDump" @@ -625,24 +644,26 @@ #define D_CMND_IRHVAC "IRHVAC" // Commands xdrv_snfbridge.ino +#define D_CMND_RFCODE "RfCode" +#define D_CMND_RFHIGH "RfHigh" +#define D_CMND_RFHOST "RfHost" #define D_CMND_RFKEY "RfKey" -#define D_CMND_RFDEFAULT "RfDefault" +#define D_CMND_RFLOW "RfLow" +#define D_CMND_RFSYNC "RfSync" // Commands xdrv_snfled.ino #define D_CMND_COLOR "Color" #define D_CMND_COLORTEMPERATURE "CT" #define D_CMND_DIMMER "Dimmer" +#define D_CMND_LED "Led" #define D_CMND_LEDTABLE "LedTable" #define D_CMND_FADE "Fade" -#define D_CMND_SPEED "Speed" -#define D_CMND_WAKEUPDURATION "WakeUpDuration" -#define D_CMND_WAKEUP "Wakeup" - -// Commands xdrv_ws2812.ino #define D_CMND_PIXELS "Pixels" -#define D_CMND_LED "Led" -#define D_CMND_WIDTH "Width" #define D_CMND_SCHEME "Scheme" +#define D_CMND_SPEED "Speed" +#define D_CMND_WAKEUP "Wakeup" +#define D_CMND_WAKEUPDURATION "WakeUpDuration" +#define D_CMND_WIDTH "Width" // Commands xsns_hlw8012.ino #define D_CMND_POWERLOW "PowerLow" @@ -666,3 +687,5 @@ #define D_CMND_SAFEPOWERWINDOW "SafePowerWindow" #define D_CMND_MAXENERGY "MaxEnergy" #define D_CMND_MAXENERGYSTART "MaxEnergyStart" + +#endif // _LANGUAGE_EN_GB_H_ \ No newline at end of file diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 9e39fc2e4..38a28f543 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -17,9 +17,13 @@ along with this program. If not, see . */ +#ifndef _LANGUAGE_NL_NL_H_ +#define _LANGUAGE_NL_NL_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. @@ -134,6 +138,7 @@ #define D_POWERFACTOR "Factor" #define D_POWERUSAGE "Vermogen" #define D_PRESSURE "Luchtdruk" +#define D_PRESSUREATSEALEVEL "ZeeLuchtdruk" #define D_PROGRAM_FLASH_SIZE "Programma Flash Grootte" #define D_PROGRAMFLASHSIZE "ProgrammaFlashGrootte" #define D_PROGRAM_SIZE "Programma Grootte" @@ -163,6 +168,7 @@ #define D_STOP "Stop" #define D_SUBNET_MASK "Subnet Masker" #define D_SUBNETMASK "Subnetmasker" +#define D_SUBSCRIBE_TO "Abonneer op" #define D_SUCCESSFUL "Gelukt" #define D_SWITCH "Schakelaar" #define D_SYNC "Sync" @@ -182,8 +188,9 @@ #define D_UPGRADE "opwaarderen" #define D_UPLOAD "Verzenden" #define D_UPTIME "Bedrijfstijd" -#define D_UTC_TIME "UTC" #define D_USER "Gebruiker" +#define D_UTC_TIME "UTC" +#define D_UV_LEVEL "UV niveau" #define D_VCC "Vcc" #define D_VERSION "Versie" #define D_VOLTAGE "Spanning" @@ -242,6 +249,7 @@ #define D_SYSLOG_HOST_NOT_FOUND "Syslog Host niet gevonden" // webserver.ino +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - opwaarderen" #define D_WEBSERVER_ACTIVE_ON "Webserver actief op" #define D_WITH_IP_ADDRESS "met IP adres" #define D_WEBSERVER_STOPPED "Webserver gestopt" @@ -336,7 +344,7 @@ #define D_ESP_CHIP_ID "ESP Chip Id" #define D_FLASH_CHIP_ID "Flash Chip Id" #define D_FLASH_CHIP_SIZE "Flash Grootte" -#define D_FREE_PROGRAM_SPACE "Vrij programma ruimte" +#define D_FREE_PROGRAM_SPACE "Programma ruimte over" #define D_UPGRADE_BY_WEBSERVER "Opwaarderen dmv webserver" #define D_OTA_URL "OTA Url" @@ -366,27 +374,28 @@ #define D_DOMOTICZ_KEY_IDX "Toets idx" #define D_DOMOTICZ_SWITCH_IDX "Schakelaar idx" #define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define DOMOTICZ_SENSORS_MAX_STRING_LENGTH 14 #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 "Spanning" + #define D_DOMOTICZ_CURRENT "Stroom" #define D_DOMOTICZ_UPDATE_TIMER "Bijwerk timer" -#define D_CONFIGURE_DOMOTICZ "Configureer Domoticz" // xdrv_ir-send.ino #define D_INVALID_JSON "Ongeldig JSON" #define D_PROTOCOL_NOT_SUPPORTED "Protocol wordt niet ondersteund" -#define D_IRSEND_PROTOCOL "PROTOCOL" -#define D_IRSEND_BITS "BITS" -#define D_IRSEND_DATA "DATA" +#define D_IR_PROTOCOL "PROTOCOL" +#define D_IR_BITS "BITS" +#define D_IR_DATA "DATA" #define D_IRHVAC_VENDOR "VENDOR" #define D_IRHVAC_POWER "POWER" #define D_IRHVAC_MODE "MODE" #define D_IRHVAC_FANSPEED "FANSPEED" #define D_IRHVAC_TEMP "TEMP" +#define D_IRRECEIVED "IrReceived" // xdrv_snfbridge.ino #define D_RFRECEIVED "RfReceived" @@ -397,6 +406,7 @@ #define D_LEARNING_ACTIVE "Leren actief" #define D_LEARN_FAILED "Leren mislukt" #define D_LEARNED "Geleerd" +#define D_SAVED "Opgeslagen" // xdrv_wemohue.ino #define D_MULTICAST_DISABLED "Multicast uitgeschakeld" @@ -452,18 +462,23 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_IRREMOTE "IRremote" +#define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Switch" // Suffix "1" #define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relais" // Suffix "1I" -#define D_SENSOR_LED "Led" // Suffix "1I" +#define D_SENSOR_RELAY "Relais" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" #define D_SENSOR_PWM "PWM" // Suffix "1" #define D_SENSOR_COUNTER "Teller" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_BACKLIGHT "BLight" // Units #define D_UNIT_AMPERE "A" -#define D_UNIT_HOUR "Hr" +#define D_UNIT_HOUR "h" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" #define D_UNIT_MICROSECOND "us" #define D_UNIT_MILLIAMPERE "mA" #define D_UNIT_MILLISECOND "ms" @@ -485,17 +500,18 @@ #define D_LOG_DSB "DSB: " #define D_LOG_HTTP "HTP: " #define D_LOG_I2C "I2C: " +#define D_LOG_IRR "IRR: " #define D_LOG_LOG "LOG: " #define D_LOG_MODULE "MOD: " #define D_LOG_MDNS "DNS: " #define D_LOG_MQTT "MQT: " #define D_LOG_OTHER "OTH: " #define D_LOG_RESULT "RSL: " +#define D_LOG_SERIAL "SER: " #define D_LOG_SHT1 "SHT: " #define D_LOG_UPLOAD "UPL: " #define D_LOG_UPNP "UPP: " #define D_LOG_WIFI "WIF: " -#define D_LOG_SERIAL "SER: " // Result #define D_RSLT_RESULT "RESULTAAT" @@ -564,6 +580,8 @@ #define D_NOT_SUPPORTED "Not supported" #define D_CMND_GPIOS "GPIOs" #define D_CMND_PWM "PWM" +#define D_CMND_PWMFREQUENCY "PWMFrequency" +#define D_CMND_PWMRANGE "PWMRange" #define D_CMND_COUNTER "Counter" #define D_CMND_COUNTERTYPE "CounterType" #define D_CMND_COUNTERDEBOUNCE "CounterDebounce" @@ -606,6 +624,7 @@ #define D_RESET_AND_RESTARTING "Reset en herstarten" #define D_ONE_TO_RESET "1 voor reset" #define D_CMND_TIMEZONE "Timezone" +#define D_CMND_ALTITUDE "Altitude" #define D_CMND_LEDPOWER "LedPower" #define D_CMND_LEDSTATE "LedState" #define D_CMND_CFGDUMP "CfgDump" @@ -625,24 +644,26 @@ #define D_CMND_IRHVAC "IRHVAC" // Commands xdrv_snfbridge.ino +#define D_CMND_RFCODE "RfCode" +#define D_CMND_RFHIGH "RfHigh" +#define D_CMND_RFHOST "RfHost" #define D_CMND_RFKEY "RfKey" -#define D_CMND_RFDEFAULT "RfDefault" +#define D_CMND_RFLOW "RfLow" +#define D_CMND_RFSYNC "RfSync" // Commands xdrv_snfled.ino #define D_CMND_COLOR "Color" #define D_CMND_COLORTEMPERATURE "CT" #define D_CMND_DIMMER "Dimmer" +#define D_CMND_LED "Led" #define D_CMND_LEDTABLE "LedTable" #define D_CMND_FADE "Fade" -#define D_CMND_SPEED "Speed" -#define D_CMND_WAKEUPDURATION "WakeUpDuration" -#define D_CMND_WAKEUP "Wakeup" - -// Commands xdrv_ws2812.ino #define D_CMND_PIXELS "Pixels" -#define D_CMND_LED "Led" -#define D_CMND_WIDTH "Width" #define D_CMND_SCHEME "Scheme" +#define D_CMND_SPEED "Speed" +#define D_CMND_WAKEUP "Wakeup" +#define D_CMND_WAKEUPDURATION "WakeUpDuration" +#define D_CMND_WIDTH "Width" // Commands xsns_hlw8012.ino #define D_CMND_POWERLOW "PowerLow" @@ -666,3 +687,5 @@ #define D_CMND_SAFEPOWERWINDOW "SafePowerWindow" #define D_CMND_MAXENERGY "MaxEnergy" #define D_CMND_MAXENERGYSTART "MaxEnergyStart" + +#endif // _LANGUAGE_NL_NL_H_ \ No newline at end of file diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h new file mode 100644 index 000000000..46f0d08f8 --- /dev/null +++ b/sonoff/language/pl-PL.h @@ -0,0 +1,691 @@ +/* + pl-PL.h - localization for Polish without fonetick - Poland for Sonoff-Tasmota + + Copyright (C) 2017 Theo Arends (translated by roblad - Robert L.) + + 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_PL_PL_H_ +#define _LANGUAGE_PL_PL_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 "PonWtoSroCzwPiaSobNie" +#define D_MONTH3LIST "StyLutMarKwiMajCzeLipSieWrzPazLisGru" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ABORTED "Anulowany" +#define D_ACTIVE "Aktywny" +#define D_ADDRESS "Adres" +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Jakosc powietrza" +#define D_AIRQUALITY "JakPowietrza" +#define D_AP "AP" // Access Point +#define D_APMAC_ADDRESS "APMac" +#define D_APPENDED "Dolaczony" +#define D_AS "jak" +#define D_AUTO "AUTO" +#define D_BAUDRATE "Szybkosc transmisji" +#define D_BLINK "Miganie" +#define D_BLINKOFF "MiganieWyl" +#define D_BOOTVERSION "Uruchomienie" +#define D_BOOT_COUNT "Licznik uruchomienia" +#define D_BOOTCOUNT "LiczUruchomienia" +#define D_BRIGHTLIGHT "Jasny" +#define D_BUILDDATETIME "ZbudowanoDataCzas" +#define D_BUTTON "Przycisk" +#define D_CELSIUS "Celsiusza" +#define D_CODE "kod" // Button code +#define D_COLDLIGHT "Zimny" +#define D_COMMAND "Komenda" +#define D_CONNECTED "Polaczony" +#define D_COREVERSION "Wersja" +#define D_COUNT "Licz" +#define D_COUNTER "Licznik" +#define D_CURRENT "Biezacy" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "Ciemny" +#define D_DEBUG "Debug" +#define D_DISABLED "Zablokowany" +#define D_DNS_SERVER "Server DNS" +#define D_DNSSERVER "ServerDNS" +#define D_DONE "Wykonane" +#define D_DST_TIME "DST" +#define D_EMPTY "Pusty" +#define D_EMULATION "Emulacja" +#define D_ENABLED "Otwarty" +#define D_ENDDST "KoniecDST" // End Daylight Savings Time +#define D_ERASE "Nadpisz" +#define D_ERROR "Blad" +#define D_EVERY "Kazdy" +#define D_FAHRENHEIT "Fahrenheita" +#define D_FAILED "Bledny" +#define D_FALLBACK "Awaryjny" +#define D_FALLBACK_TOPIC "Zastepczy temat" +#define D_FALLBACKTOPIC "ZastepczyTemat" +#define D_FALSE "Falsz" +#define D_FILE "Plik" +#define D_FLASHMODE "FlashMode" +#define D_FLASHSIZE "FlashWielkosc" +#define D_FREE_MEMORY "Wolna pamiec" +#define D_FREEMEMORY "Wolne" +#define D_FROM "z" +#define D_GATEWAY "Brama" +#define D_GROUP "Grupa" +#define D_HEAPSIZE "Stos" +#define D_HIGH "Wysoki" +#define D_HOST "Serwer" +#define D_HOSTNAME "Nazwa serwera" +#define D_HUMIDITY "Wilgotnosc" +#define D_ILLUMINANCE "Oswietlenie" +#define D_IMMEDIATE "Natychmiastowe" // Button immediate +#define D_INDEX "Indeks" +#define D_INFO "Informacja" +#define D_INITIALIZED "Zainicjowany" +#define D_IP_ADDRESS "Adres IP" +#define D_LIGHT "Swiatlo" +#define D_LOCAL_TIME "Lokalny" +#define D_LOW "Niski" +#define D_LWT "LWT" +#define D_MAC "Mac" +#define D_MASK "Maska" +#define D_MODULE "Modul" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "wielokrotne-nacisniecie" +#define D_NO "Nie" +#define D_NOISE "Halas" +#define D_NONE "Brak" +#define D_OFF "Wylaczony" +#define D_OFFLINE "Nieaktywny" +#define D_OK "Ok" +#define D_ON "Wlaczony" +#define D_ONLINE "Aktywny" +#define D_OR "lub" +#define D_PASSWORD "Haslo" +#define D_PERIOD "Okres" +#define D_PORT "Port" +#define D_POWER_FACTOR "Wspolczynik mocy" +#define D_POWERFACTOR "WspolczynikMocy" +#define D_POWERUSAGE "Moc" +#define D_PRESSURE "Cisnienie" +#define D_PRESSUREATSEALEVEL "Cisnienie na poziomie morza" +#define D_PROGRAM_FLASH_SIZE "Wielkosc programu flash" +#define D_PROGRAMFLASHSIZE "ProgramFlashSize" +#define D_PROGRAM_SIZE "Wielkosc programu" +#define D_PROGRAMSIZE "ProgramSize" +#define D_PROJECT "Projekt" +#define D_RECEIVED "Otrzymany" +#define D_RESTART "Restart" +#define D_RESTARTING "Restartowanie" +#define D_RESTART_REASON "Przyczyna restartu" +#define D_RESTARTREASON "PrzyczynaRestartu" +#define D_RESTORE "Przywracanie" +#define D_RETAINED "Zachowane" +#define D_SAVE "Zapisz" +#define D_SAVEADDRESS "AdresZapisu" +#define D_SAVECOUNT "LicznikZapisu" +#define D_SAVESTATE "StanZapisu" +#define D_SDKVERSION "SDK" +#define D_SELECTED "Wybrany" +#define D_SENSOR "Czujnik" +#define D_SERIAL "Serial" +#define D_BYTES "Bajtow" +#define D_SSID "SSID" +#define D_START "Start" +#define D_STARTED "Uruchomiony" +#define D_STARTDST "StartDST" // Start Daylight Savings Time +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Maska podsieci" +#define D_SUBNETMASK "MaskaPodsieci" +#define D_SUBSCRIBE_TO "Subskrybuj do" +#define D_SUCCESSFUL "Powodzenie" +#define D_SWITCH "Przelacznik" +#define D_SYNC "Sync" +#define D_SYS "System " // Sys log +#define D_TEMPERATURE "Temperatura" +#define D_TEMPERATURE_UNIT "JednTemp" +#define D_TIME "Czas" +#define D_TO "do" +#define D_TODAY "Dzisiaj" +#define D_TOGGLE "Przelacz" +#define D_TOPIC "Temat" +#define D_TOTAL "Suma" +#define D_TRANSMIT "Wyslij" +#define D_TRUE "Prawda" +#define D_TYPE "Typ" +#define D_UNKNOWN "Nieznany" +#define D_UPGRADE "aktualizacji" +#define D_UPLOAD "Wgraj" +#define D_UPTIME "Uptime" +#define D_USER "Uzytkownik" +#define D_UTC_TIME "UTC" +#define D_UV_LEVEL "Poziom UV" +#define D_VCC "VCC" +#define D_VERSION "Wersja" +#define D_VOLTAGE "Napiecie" +#define D_WARMLIGHT "Nagrzanie" +#define D_WEB "Web" // Web log +#define D_WEB_SERVER "Web Server" +#define D_WIFI "Wifi" +#define D_WRONG "Bledny" +#define D_YESTERDAY "Wczoraj" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Zapisane do pamieci flash w" +#define D_LOADED_FROM_FLASH_AT "Wczytane z pamieci flash z" +#define D_USE_DEFAULTS "Uzyj domyslnych" +#define D_ERASED_SECTOR "Wymazany sektor" + +// sonoff.ino +#define D_LEVEL_10 "poziom 1-0" +#define D_LEVEL_01 "poziom 0-1" +#define D_SERIAL_LOGGING_DISABLED "Wylaczony dziennik na porcie szeregowym" +#define D_SYSLOG_LOGGING_REENABLED "Wznowiono zapis do Syslog" + +#define D_SET_BAUDRATE_TO "Ustaw szybkosc transmisji na" +#define D_RECEIVED_TOPIC "Otrzymany temat" +#define D_DATA_SIZE "Wielkosc danych" +#define D_ANALOG_INPUT0 "Wej_analogowe" + +#define D_FINGERPRINT "Weryfikuj odcisk TLS..." +#define D_TLS_CONNECT_FAILED_TO "Nieudane polaczenie TLS do" +#define D_RETRY_IN "Sprobuj ponownie" +#define D_VERIFIED "Zweryfikowano" +#define D_INSECURE "Nieprawidlowe polaczenie z powodu blednego odcisku TLS" +#define D_CONNECT_FAILED_TO "Nie udalo sie nawiazac polaczenia" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Petla zablokowana" +#define D_WPS_FAILED_WITH_STATUS "Blad WPSconfig ze statusem" +#define D_ACTIVE_FOR_1_MINUTE "aktywny 1 minute" +#define D_FAILED_TO_START "nie udalo sie uruchomic" +#define D_PATCH_ISSUE_2186 "Blad latki 2186" +#define D_CONNECTING_TO_AP "Laczenie z AP" +#define D_IN_MODE "w trybie" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Polaczenie nie powiodlo sie, poniewaz nie otrzymano adresu IP" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Polaczenie nie powiodlo sie jako AP nie mozna osiagnac" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Polaczenie nie powiodlo sie z nieprawidlowym haslem dostepu AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Nie udalo sie nawiazac polaczenia, limit czasu AP przekroczony" +#define D_ATTEMPTING_CONNECTION "Proba polaczenia..." +#define D_CHECKING_CONNECTION "Sprawdzanie polaczenia..." +#define D_QUERY_DONE "Wykonano zapytanie. Znaleziono uslugi MQTT" +#define D_MQTT_SERVICE_FOUND "Usluga MQTT została znaleziona" +#define D_I2CSCAN_DEVICES_FOUND_AT "Znaleziono urządzenie(a) na" +#define D_FOUND_AT "znalezione w" +#define D_I2CSCAN_UNKNOWN_ERROR_AT "Nieznany blad w" +#define D_I2CSCAN_NO_DEVICES_FOUND "Nie znaleziono urzadzen" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nie znaleziony" + +// webserver.ino +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL - prosze uaktualnic" +#define D_WEBSERVER_ACTIVE_ON "Aktywny serwer Web" +#define D_WITH_IP_ADDRESS "z adresem IP" +#define D_WEBSERVER_STOPPED "Serwer Web zatrzymany" +#define D_FILE_NOT_FOUND "Plik nie odnaleziony" +#define D_REDIRECTED "Przekierowano do wlasnego portalu" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Menedzer Wifi ustawia punkt dostepowy i zachowuje stacje" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Menedzer sieci Wi-Fi Access Point" +#define D_TRYING_TO_CONNECT "Probuje polaczyc urzadzenie z siecia" + +#define D_RESTART_IN "Zrestartuj" +#define D_SECONDS "sekund" +#define D_DEVICE_WILL_RESTART "Urzadzenie zrestartuje sie za kilka sekund" +#define D_BUTTON_TOGGLE "Przelacznik" +#define D_CONFIGURATION "Konfiguracja" +#define D_INFORMATION "Informacje" +#define D_FIRMWARE_UPGRADE "Uaktualnienie oprogramowania" +#define D_CONSOLE "Konsola" +#define D_CONFIRM_RESTART "Potwierdz restart" + +#define D_CONFIGURE_MODULE "Konfiguruj modul" +#define D_CONFIGURE_WIFI "Konfiguruj WiFi" +#define D_CONFIGURE_MQTT "Konfiguruj MQTT" +#define D_CONFIGURE_DOMOTICZ "Konfiguruj Domoticz" +#define D_CONFIGURE_LOGGING "Konfiguruj zapis dziennika" +#define D_CONFIGURE_OTHER "Konfiguruj inne" +#define D_CONFIRM_RESET_CONFIGURATION "Potwierdz reset ustawien" +#define D_RESET_CONFIGURATION "Reset ustawien" +#define D_BACKUP_CONFIGURATION "Kopia ustawien" +#define D_RESTORE_CONFIGURATION "Przywrocenie ustawien" +#define D_MAIN_MENU "Menu glowne" + +#define D_MODULE_PARAMETERS "Parametery modulu" +#define D_MODULE_TYPE "Typ modulu" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Parametry WiFi" +#define D_SCAN_FOR_WIFI_NETWORKS "Skanuj sieci WiFi" +#define D_SCAN_DONE "Skan wykonany" +#define D_NO_NETWORKS_FOUND "Nie znaleziono sieci" +#define D_REFRESH_TO_SCAN_AGAIN "Odswiez aby ponownie zeskanowac" +#define D_DUPLICATE_ACCESSPOINT "Kopiuj AP" +#define D_SKIPPING_LOW_QUALITY "Pominieto z powodu niskiej jakości sygnalu" +#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 "Haslo AP1" +#define D_AP2_SSID "AP2 SSID" +#define D_AP2_PASSWORD "Haslo AP2" + +#define D_MQTT_PARAMETERS "Parametery MQTT" +#define D_CLIENT "Klient" +#define D_FULL_TOPIC "Pelen temat" + +#define D_LOGGING_PARAMETERS "Opcje dziennika" +#define D_LOG_LEVEL "poziom dziennika" +#define D_MORE_DEBUG "Wiecej informacji debugujacych" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog port" +#define D_TELEMETRY_PERIOD "Okres telemetrii" + +#define D_OTHER_PARAMETERS "Inne parametery" +#define D_WEB_ADMIN_PASSWORD "Haslo administratora Web" +#define D_MQTT_ENABLE "MQTT aktywne" +#define D_FRIENDLY_NAME "Przyjazna nazwa" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "single device" +#define D_MULTI_DEVICE "multi device" + +#define D_SAVE_CONFIGURATION "Zapisz ustawienia" +#define D_CONFIGURATION_SAVED "Ustawienia zapisane" +#define D_CONFIGURATION_RESET "Ustawienia zresetowane" + +#define D_PROGRAM_VERSION "Wersja programu" +#define D_BUILD_DATE_AND_TIME "Dzien i godzina kompilacji" +#define D_CORE_AND_SDK_VERSION "Wersja Core/SDK" +#define D_FLASH_WRITE_COUNT "Liczba zapisow do pamieci" +#define D_MAC_ADDRESS "Adres Mac" +#define D_MQTT_HOST "Host MQTT" +#define D_MQTT_PORT "Port MQTT" +#define D_MQTT_CLIENT "Klient MQTT" +#define D_MQTT_USER "Uzytkownik MQTT" +#define D_MQTT_TOPIC "Temat MQTT" +#define D_MQTT_GROUP_TOPIC "Temat grupy MQTT" +#define D_MQTT_FULL_TOPIC "Pelen temat MQTT" +#define D_MDNS_DISCOVERY "Wykrywanie mDNS" +#define D_MDNS_ADVERTISE "Rozglaszanie mDNS" +#define D_ESP_CHIP_ID "ID ukladu ESP" +#define D_FLASH_CHIP_ID "ID ukladu pamieci flash" +#define D_FLASH_CHIP_SIZE "Rozmiar flash" +#define D_FREE_PROGRAM_SPACE "Wolne miejsce programu" + +#define D_UPGRADE_BY_WEBSERVER "Aktualizacja z serwera Web" +#define D_OTA_URL "URL OTA" +#define D_START_UPGRADE "Start aktualizacji" +#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizacja poprzez wgranie pliku" +#define D_UPLOAD_STARTED "Wgrywanie rozpoczete" +#define D_UPGRADE_STARTED "Aktualizacja rozpoczeta" +#define D_UPLOAD_DONE "Wgrywanie zakonczone" +#define D_UPLOAD_ERR_1 "Nie wybrano pliku" +#define D_UPLOAD_ERR_2 "Niewystarczajaca ilosc miejsca" +#define D_UPLOAD_ERR_3 "Magiczny bajt jest inny niz 0xE9" +#define D_UPLOAD_ERR_4 "Rozmiar programu jest wiekszy niz rzeczywisty rozmiar pamieci flash" +#define D_UPLOAD_ERR_5 "Wgrywanie, bufor niezgodnosci stanu porownywanych bitow" +#define D_UPLOAD_ERR_6 "Blad wgrywania. Uruchomiono zapis do dziennika na poziomie 3" +#define D_UPLOAD_ERR_7 "Wgrywanie przerwane" +#define D_UPLOAD_ERR_8 "Bledny plik" +#define D_UPLOAD_ERR_9 "Plik jest za duzy" +#define D_UPLOAD_ERROR_CODE "Blad wgrywania" + +#define D_ENTER_COMMAND "Wprowadz polecenie" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Wlacz poziom 2 zapisu Weblog, jesli oczekiwana jest odpowiedz" +#define D_NEED_USER_AND_PASSWORD "Wymagany uzytkownik=&haslo=" + +// xdrv_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Parametry Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Przelacznik idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Wilg" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Wilg,Cis" + #define D_DOMOTICZ_POWER_ENERGY "Moc,Energia" + #define D_DOMOTICZ_ILLUMINANCE "Oswietl." + #define D_DOMOTICZ_COUNT "Licznik" + #define D_DOMOTICZ_VOLTAGE "Napiecie" + #define D_DOMOTICZ_CURRENT "Prad" +#define D_DOMOTICZ_UPDATE_TIMER "Zaktualizuj czasomierz" + +// xdrv_ir-send.ino +#define D_INVALID_JSON "Invalid JSON" +#define D_PROTOCOL_NOT_SUPPORTED "Protokol nie jest obslugiwany" +#define D_IR_PROTOCOL "PROTOCOL" +#define D_IR_BITS "BITS" +#define D_IR_DATA "DATA" +#define D_IRHVAC_VENDOR "VENDOR" +#define D_IRHVAC_POWER "POWER" +#define D_IRHVAC_MODE "MODE" +#define D_IRHVAC_FANSPEED "FANSPEED" +#define D_IRHVAC_TEMP "TEMP" +#define D_IRRECEIVED "IrReceived" + +// xdrv_snfbridge.ino +#define D_RFRECEIVED "RfReceived" +#define D_START_LEARNING "Zacznij nauke" +#define D_SET_TO_DEFAULT "Ustaw domyslne" +#define D_DEFAULT_SENT "Domyslne wyslane" +#define D_LEARNED_SENT "Wyuczone wyslane" +#define D_LEARNING_ACTIVE "Wyuczone aktywne" +#define D_LEARN_FAILED "Uczenie niepowodzenie" +#define D_LEARNED "Wyuczone" +#define D_SAVED "Zapisane" + +// xdrv_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast jest wylaczony" +#define D_MULTICAST_REJOINED "Multicast (re)dolaczony" +#define D_MULTICAST_JOIN_FAILED "Multicast nie powiodlo sie" +#define D_FAILED_TO_SEND_RESPONSE "Nie udalo sie wyslac odpowiedzi" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo podstawowe zdarzenie" +#define D_WEMO_EVENT_SERVICE "WeMo zdarzenie service" +#define D_WEMO_SETUP "WeMo setup" +#define D_RESPONSE_SENT "Odpowiedz wyslana" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue setup" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API nie zaimplementowane" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 pakiety odpowiedzi wysylane" + +// xsns_dht.ino +#define D_TIMEOUT_WAITING_FOR "Trwa oczekiwanie" +#define D_START_SIGNAL_LOW "sygnał startowy niski" +#define D_START_SIGNAL_HIGH "sygnał startowy wysoki" +#define D_PULSE "pulse" +#define D_CHECKSUM_FAILURE "Bledna suma kontrolmna" + +// xsns_ds18b20.ino +#define D_SENSOR_BUSY "Czujnik DS18x20 zajety" +#define D_SENSOR_CRC_ERROR "Czujnik DS18x20 blad CRC" + +// xsns_hlw8012.ino +#define D_MAXPOWERREACHED "MaksMocOsiagnieta" +#define D_MAXPOWERREACHEDRETRY "MaksMocOsiagnietaPonowienie" +#define D_POWERMONITOR "MonitorMocy" +#define D_ENERGYMONITOR "MonitorEnergii" +#define D_MAXENERGYREACHED "MaksEnergiaOsiagnieta" +#define D_ENERGY_TODAY "Energia Dzisiaj" +#define D_ENERGY_YESTERDAY "Energia Wczoraj" +#define D_ENERGY_TOTAL "Energia suma" + +// xsns_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Czujnik nie otrzymal komendy ACK" +#define D_SHT1X_FOUND "SHT1X znaleziony" + +// sonoff_template.h +// Max string length is 8 characters including suffixes +#define D_SENSOR_NONE "Brak" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_DHT22 "DHT22" +#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 "Przela" // Suffix "1" +#define D_SENSOR_BUTTON "Przyci" // Suffix "1" +#define D_SENSOR_RELAY "Przek" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Liczni" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_BACKLIGHT "BLight" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_HOUR "Godz" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sektory" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" + +// Log message prefix +#define D_LOG_APPLICATION "APP: " +#define D_LOG_BRIDGE "BRG: " +#define D_LOG_CONFIG "CFG: " +#define D_LOG_COMMAND "CMD: " +#define D_LOG_DHT "DHT: " +#define D_LOG_DOMOTICZ "DOM: " +#define D_LOG_DSB "DSB: " +#define D_LOG_HTTP "HTP: " +#define D_LOG_I2C "I2C: " +#define D_LOG_IRR "IRR: " +#define D_LOG_LOG "LOG: " +#define D_LOG_MODULE "MOD: " +#define D_LOG_MDNS "DNS: " +#define D_LOG_MQTT "MQT: " +#define D_LOG_OTHER "OTH: " +#define D_LOG_RESULT "RSL: " +#define D_LOG_SERIAL "SER: " +#define D_LOG_SHT1 "SHT: " +#define D_LOG_UPLOAD "UPL: " +#define D_LOG_UPNP "UPP: " +#define D_LOG_WIFI "WIF: " + +// Result +#define D_RSLT_RESULT "REZULTAT" +#define D_RSLT_INFO "INFO" +#define D_RSLT_STATE "STAN" +#define D_RSLT_SENSOR "SENSOR" +#define D_RSLT_UPTIME "UPTIME" +#define D_RSLT_MARGINS "MARGINES" +#define D_RSLT_WARNING "OSTRZEZENIE" +#define D_RSLT_ENERGY "ENERGIA" + +// Commands +#define D_CMND_MQTTHOST "MqttHost" +#define D_CMND_MQTTPORT "MqttPort" +#define D_CMND_MQTTRETRY "MqttRetry" +#define D_CMND_STATETEXT "StateText" +#define D_CMND_MQTTFINGERPRINT "MqttFingerprint" +#define D_CMND_MQTTCLIENT "MqttClient" +#define D_CMND_MQTTUSER "MqttUser" +#define D_CMND_MQTTPASSWORD "MqttPassword" +#define D_CMND_FULLTOPIC "FullTopic" +#define D_CMND_PREFIX "Prefix" + #define PRFX_MAX_STRING_LENGTH 5 + #define D_CMND "cmnd" + #define D_STAT "stat" + #define D_TELE "tele" +#define D_CMND_GROUPTOPIC "GroupTopic" +#define D_CMND_TOPIC "Topic" +#define D_CMND_BUTTONTOPIC "ButtonTopic" +#define D_CMND_SWITCHTOPIC "SwitchTopic" +#define D_CMND_BUTTONRETAIN "ButtonRetain" +#define D_CMND_SWITCHRETAIN "SwitchRetain" +#define D_CMND_POWERRETAIN "PowerRetain" +#define D_CMND_SENSORRETAIN "SensorRetain" +#define D_CMND_BACKLOG "Backlog" +#define D_CMND_DELAY "Delay" +#define D_CMND_STATUS "Status" + #define D_STATUS1_PARAMETER "PRM" + #define D_STATUS2_FIRMWARE "FWR" + #define D_STATUS3_LOGGING "LOG" + #define D_STATUS4_MEMORY "MEM" + #define D_STATUS5_NETWORK "NET" + #define D_STATUS6_MQTT "MQT" + #define D_STATUS7_TIME "TIM" + #define D_STATUS8_POWER "PWR" + #define D_STATUS9_MARGIN "PTH" + #define D_STATUS10_SENSOR "SNS" + #define D_STATUS11_STATUS "STS" +#define D_CMND_POWER "Power" + #define D_RSLT_POWER "POWER" +#define D_CMND_POWERONSTATE "PowerOnState" +#define D_CMND_PULSETIME "PulseTime" +#define D_CMND_BLINKTIME "BlinkTime" +#define D_CMND_BLINKCOUNT "BlinkCount" +#define D_CMND_SAVEDATA "SaveData" +#define D_CMND_SETOPTION "SetOption" +#define D_CMND_TEMPERATURE_RESOLUTION "TempRes" +#define D_CMND_HUMIDITY_RESOLUTION "HumRes" +#define D_CMND_PRESSURE_RESOLUTION "PressRes" +#define D_CMND_POWER_RESOLUTION "WattRes" +#define D_CMND_VOLTAGE_RESOLUTION "VoltRes" +#define D_CMND_ENERGY_RESOLUTION "EnergyRes" +#define D_CMND_MODULE "Module" +#define D_CMND_MODULES "Modules" +#define D_CMND_GPIO "GPIO" + #define D_NOT_SUPPORTED "Not supported" +#define D_CMND_GPIOS "GPIOs" +#define D_CMND_PWM "PWM" +#define D_CMND_PWMFREQUENCY "PWMFrequency" +#define D_CMND_PWMRANGE "PWMRange" +#define D_CMND_COUNTER "Counter" +#define D_CMND_COUNTERTYPE "CounterType" +#define D_CMND_COUNTERDEBOUNCE "CounterDebounce" +#define D_CMND_SLEEP "Sleep" +#define D_CMND_UPLOAD "Upload" +#define D_CMND_UPGRADE "Upgrade" + #define D_ONE_OR_GT "1 or >%s to upgrade" +#define D_CMND_OTAURL "OtaUrl" +#define D_CMND_SERIALLOG "SerialLog" +#define D_CMND_SYSLOG "SysLog" +#define D_CMND_LOGHOST "LogHost" +#define D_CMND_LOGPORT "LogPort" +#define D_CMND_IPADDRESS "IPAddress" +#define D_CMND_NTPSERVER "NtpServer" +#define D_CMND_AP "Ap" +#define D_CMND_SSID "SSID" +#define D_CMND_PASSWORD "Password" +#define D_CMND_HOSTNAME "Hostname" +#define D_CMND_WIFICONFIG "WifiConfig" + #define WCFG_MAX_STRING_LENGTH 12 + #define D_WCFG_0_RESTART "Restart" + #define D_WCFG_1_SMARTCONFIG "SmartConfig" + #define D_WCFG_2_WIFIMANAGER "WifiManager" + #define D_WCFG_3_WPSCONFIG "WPSConfig" + #define D_WCFG_4_RETRY "Retry" + #define D_WCFG_5_WAIT "Wait" +#define D_CMND_FRIENDLYNAME "FriendlyName" +#define D_CMND_SWITCHMODE "SwitchMode" +#define D_CMND_WEBSERVER "Webserver" + #define D_WEBSERVER_MODE "WebServerMode" + #define D_ACTIVE_FOR "Active for" + #define D_ON_DEVICE "on" +#define D_CMND_WEBPASSWORD "WebPassword" +#define D_CMND_WEBLOG "WebLog" +#define D_CMND_EMULATION "Emulation" +#define D_CMND_TELEPERIOD "TelePeriod" +#define D_CMND_RESTART "Restart" + #define D_ONE_TO_RESTART "1 to restart" +#define D_CMND_RESET "Reset" + #define D_RESET_AND_RESTARTING "Reset and Restarting" + #define D_ONE_TO_RESET "1 to reset" +#define D_CMND_TIMEZONE "Timezone" +#define D_CMND_ALTITUDE "Altitude" +#define D_CMND_LEDPOWER "LedPower" +#define D_CMND_LEDSTATE "LedState" +#define D_CMND_CFGDUMP "CfgDump" +#define D_CMND_I2CSCAN "I2CScan" +#define D_CMND_EXCEPTION "Exception" + +// Commands xdrv_domoticz.ino +#define D_CMND_DOMOTICZ "Domoticz" +#define D_CMND_IDX "Idx" +#define D_CMND_KEYIDX "KeyIdx" +#define D_CMND_SWITCHIDX "SwitchIdx" +#define D_CMND_SENSORIDX "SensorIdx" +#define D_CMND_UPDATETIMER "UpdateTimer" + +// Commands xdrv_ir_send.ino +#define D_CMND_IRSEND "IRSend" +#define D_CMND_IRHVAC "IRHVAC" + +// Commands xdrv_snfbridge.ino +#define D_CMND_RFCODE "RfCode" +#define D_CMND_RFHIGH "RfHigh" +#define D_CMND_RFHOST "RfHost" +#define D_CMND_RFKEY "RfKey" +#define D_CMND_RFLOW "RfLow" +#define D_CMND_RFSYNC "RfSync" + +// Commands xdrv_snfled.ino +#define D_CMND_COLOR "Color" +#define D_CMND_COLORTEMPERATURE "CT" +#define D_CMND_DIMMER "Dimmer" +#define D_CMND_LED "Led" +#define D_CMND_LEDTABLE "LedTable" +#define D_CMND_FADE "Fade" +#define D_CMND_PIXELS "Pixels" +#define D_CMND_SCHEME "Scheme" +#define D_CMND_SPEED "Speed" +#define D_CMND_WAKEUP "Wakeup" +#define D_CMND_WAKEUPDURATION "WakeUpDuration" +#define D_CMND_WIDTH "Width" + +// Commands xsns_hlw8012.ino +#define D_CMND_POWERLOW "PowerLow" +#define D_CMND_POWERHIGH "PowerHigh" +#define D_CMND_VOLTAGELOW "VoltageLow" +#define D_CMND_VOLTAGEHIGH "VoltageHigh" +#define D_CMND_CURRENTLOW "CurrentLow" +#define D_CMND_CURRENTHIGH "CurrentHigh" +#define D_CMND_ENERGYRESET "EnergyReset" +#define D_CMND_HLWPCAL "HlwPcal" +#define D_CMND_HLWPSET "HlwPset" +#define D_CMND_HLWUCAL "HlwUcal" +#define D_CMND_HLWUSET "HlwUset" +#define D_CMND_HLWICAL "HlwIcal" +#define D_CMND_HLWISET "HlwIset" +#define D_CMND_MAXPOWER "MaxPower" +#define D_CMND_MAXPOWERHOLD "MaxPowerHold" +#define D_CMND_MAXPOWERWINDOW "MaxPowerWindow" +#define D_CMND_SAFEPOWER "SafePower" +#define D_CMND_SAFEPOWERHOLD "SafePowerHold" +#define D_CMND_SAFEPOWERWINDOW "SafePowerWindow" +#define D_CMND_MAXENERGY "MaxEnergy" +#define D_CMND_MAXENERGYSTART "MaxEnergyStart" + +#endif // _LANGUAGE_PL_PL_H_ \ No newline at end of file diff --git a/sonoff/settings.h b/sonoff/settings.h index cd0df85e7..e71a8fee5 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -17,12 +17,15 @@ along with this program. If not, see . */ +#ifndef _SETTINGS_H_ +#define _SETTINGS_H_ + #define PARAM8_SIZE 23 // Number of param bytes typedef union { // Restricted by MISRA-C Rule 18.4 but so usefull... uint32_t data; // Allow bit manipulation using SetOption struct { - uint32_t savestate : 1; // bit 0 + uint32_t save_state : 1; // bit 0 uint32_t button_restrict : 1; // bit 1 uint32_t value_units : 1; // bit 2 uint32_t mqtt_enabled : 1; // bit 3 @@ -37,9 +40,9 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t stop_flash_rotate : 1; // bit 12 (v5.2.0) uint32_t button_single : 1; // bit 13 (v5.4.0) uint32_t interlock : 1; // bit 14 (v5.6.0) - uint32_t spare15 : 1; - uint32_t spare16 : 1; - uint32_t spare17 : 1; + uint32_t pwm_control : 1; // bit 15 (v5.8.1) + uint32_t ws_clock_reverse : 1; // bit 16 (v5.8.1) + uint32_t decimal_text : 1; // bit 17 (v5.8.1) uint32_t spare18 : 1; uint32_t wattage_resolution : 1; uint32_t voltage_resolution : 1; @@ -49,175 +52,200 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t humidity_resolution : 2; uint32_t temperature_resolution : 2; }; -} sysBitfield; +} SysBitfield; struct SYSCFG { - unsigned long cfg_holder; - unsigned long saveFlag; - unsigned long version; - unsigned long bootcount; - sysBitfield flag; // Add flag since 5.0.2 - int16_t savedata; + unsigned long cfg_holder; // 000 + unsigned long save_flag; // 004 + unsigned long version; // 008 + unsigned long bootcount; // 00C + SysBitfield flag; // 010 Add flag since 5.0.2 + int16_t save_data; // 014 + int8_t timezone; // 016 + char ota_url[101]; // 017 + char mqtt_prefix[3][11]; // 07C - int8_t timezone; - char otaUrl[101]; + byte free_09D[1]; // 09D - char mqtt_prefix[3][11]; // was ex_friendlyname[33] until 3.2.5 + byte seriallog_level; // 09E + uint8_t sta_config; // 09F + byte sta_active; // 0A0 + char sta_ssid[2][33]; // 0A1 + char sta_pwd[2][65]; // 0E3 + char hostname[33]; // 165 + char syslog_host[33]; // 186 - byte serial_enable; // Not used (ever) - byte seriallog_level; - uint8_t sta_config; - byte sta_active; - char sta_ssid[2][33]; - char sta_pwd[2][65]; - char hostname[33]; - char syslog_host[33]; - uint16_t syslog_port; - byte syslog_level; - uint8_t webserver; - byte weblog_level; + byte free_1A7[1]; // 1A7 - char mqtt_fingerprint[60]; - char mqtt_host[33]; - uint16_t mqtt_port; - char mqtt_client[33]; - char mqtt_user[33]; - char mqtt_pwd[33]; - char mqtt_topic[33]; - char button_topic[33]; - char mqtt_grptopic[33]; - char ex_state_text[3][11]; // was state_text until 5.1.6, was ex_mqtt_subtopic[33] until 4.1.1 - byte ex_mqtt_button_retain; // Not used since 5.0.2 - byte ex_mqtt_power_retain; // Not used since 5.0.2 - byte ex_value_units; // Not used since 5.0.2 - byte ex_button_restrict; // Not used since 5.0.2 - uint16_t tele_period; + uint16_t syslog_port; // 1A8 + byte syslog_level; // 1AA + uint8_t webserver; // 1AB + byte weblog_level; // 1AC + char mqtt_fingerprint[60]; // 1AD To be freed by binary fingerprint + char mqtt_host[33]; // 1E9 + uint16_t mqtt_port; // 20A + char mqtt_client[33]; // 20C + char mqtt_user[33]; // 22D + char mqtt_pwd[33]; // 24E + char mqtt_topic[33]; // 26F + char button_topic[33]; // 290 + char mqtt_grptopic[33]; // 2B1 + uint8_t mqtt_fingerprinth[20]; // 2D2 Reserved for binary fingerprint - uint8_t power; - uint8_t ledstate; + uint16_t pwm_frequency; // 2E6 + power_t power; // 2E8 + uint16_t pwm_value[MAX_PWMS]; // 2EC - uint8_t param[PARAM8_SIZE]; // was domoticz_in_topic until 5.1.6 - char state_text[4][11]; // was domoticz_out_topic until 5.1.6 + int16_t altitude; // 2F6 Add since 5.8.0i + uint16_t tele_period; // 2F8 + uint8_t ex_power; // 2FA Not used since 5.8.0j + uint8_t ledstate; // 2FB + uint8_t param[PARAM8_SIZE]; // 2FC was domoticz_in_topic until 5.1.6 + char state_text[4][11]; // 313 - uint16_t domoticz_update_timer; - unsigned long domoticz_relay_idx[4]; - unsigned long domoticz_key_idx[4]; + byte free_33F[1]; // 33F - unsigned long hlw_pcal; - unsigned long hlw_ucal; - unsigned long hlw_ical; - unsigned long hlw_kWhtoday; - unsigned long hlw_kWhyesterday; - uint16_t hlw_kWhdoy; - uint16_t hlw_pmin; - uint16_t hlw_pmax; - uint16_t hlw_umin; - uint16_t hlw_umax; - uint16_t hlw_imin; - uint16_t hlw_imax; - uint16_t hlw_mpl; // MaxPowerLimit - uint16_t hlw_mplh; // MaxPowerLimitHold - uint16_t hlw_mplw; // MaxPowerLimitWindow - uint16_t hlw_mspl; // MaxSafePowerLimit - uint16_t hlw_msplh; // MaxSafePowerLimitHold - uint16_t hlw_msplw; // MaxSafePowerLimitWindow - uint16_t hlw_mkwh; // MaxEnergy - uint16_t hlw_mkwhs; // MaxEnergyStart + uint16_t domoticz_update_timer; // 340 + uint16_t pwm_range; // 342 - // 3.0.6 - uint16_t mqtt_retry; // was ex_pulsetime until 4.0.4 + unsigned long domoticz_relay_idx[MAX_DOMOTICZ_IDX]; // 344 + unsigned long domoticz_key_idx[MAX_DOMOTICZ_IDX]; // 354 - // 3.1.1 - uint8_t poweronstate; + unsigned long hlw_power_calibration; // 364 + unsigned long hlw_voltage_calibration; // 368 + unsigned long hlw_current_calibration; // 36C + unsigned long hlw_kWhtoday; // 370 + unsigned long hlw_kWhyesterday; // 374 + uint16_t hlw_kWhdoy; // 378 + uint16_t hlw_pmin; // 37A + uint16_t hlw_pmax; // 37C + uint16_t hlw_umin; // 37E + uint16_t hlw_umax; // 380 + uint16_t hlw_imin; // 382 + uint16_t hlw_imax; // 384 + uint16_t hlw_mpl; // 386 MaxPowerLimit + uint16_t hlw_mplh; // 388 MaxPowerLimitHold + uint16_t hlw_mplw; // 38A MaxPowerLimitWindow + uint16_t hlw_mspl; // 38C MaxSafePowerLimit + uint16_t hlw_msplh; // 38E MaxSafePowerLimitHold + uint16_t hlw_msplw; // 390 MaxSafePowerLimitWindow + uint16_t hlw_mkwh; // 392 MaxEnergy + uint16_t hlw_mkwhs; // 394 MaxEnergyStart + uint16_t mqtt_retry; // 396 + uint8_t poweronstate; // 398 - // 3.1.6 - uint16_t blinktime; - uint16_t blinkcount; + byte free_399[1]; // 399 - // 3.2.4 - uint16_t ws_pixels; - uint8_t ws_red; - uint8_t ws_green; - uint8_t ws_blue; - uint8_t ws_ledtable; - uint8_t ws_dimmer; - uint8_t ws_fade; - uint8_t ws_speed; - uint8_t ws_scheme; - uint8_t ws_width; - uint16_t ws_wakeup; + uint16_t blinktime; // 39A + uint16_t blinkcount; // 39C + uint16_t ws_pixels; // 39E Not used since 5.8.0 + uint8_t ws_red; // 3A0 Not used since 5.8.0 + uint8_t ws_green; // 3A1 Not used since 5.8.0 + uint8_t ws_blue; // 3A2 Not used since 5.8.0 + uint8_t ws_ledtable; // 3A3 Not used since 5.8.0 + uint8_t ws_dimmer; // 3A4 Not used since 5.8.0 + uint8_t ws_fade; // 3A5 Not used since 5.8.0 + uint8_t ws_speed; // 3A6 Not used since 5.8.0 + uint8_t ws_scheme; // 3A7 Not used since 5.8.0 + uint8_t ex_ws_width; // 3A8 Not used since 5.8.0 - // 3.2.5 - char friendlyname[4][33]; + byte free_3A9[1]; // 3A9 - // 3.2.8 - char switch_topic[33]; - byte ex_mqtt_switch_retain; // Not used since 5.0.2 - uint8_t ex_mqtt_enabled; // Not used since 5.0.2 + uint16_t ws_wakeup; // 3AA Not used since 5.8.0 + char friendlyname[MAX_FRIENDLYNAMES][33]; // 3AC + char switch_topic[33]; // 430 - // 3.2.12 - uint8_t sleep; + byte free_451[2]; // 451 - // 3.9.3 - uint16_t domoticz_switch_idx[4]; - uint16_t domoticz_sensor_idx[12]; - uint8_t module; - mytmplt my_module; - uint16_t led_pixels; - uint8_t led_color[5]; - uint8_t led_table; - uint8_t led_dimmer[3]; - uint8_t led_fade; - uint8_t led_speed; - uint8_t led_scheme; - uint8_t led_width; - uint16_t led_wakeup; + uint8_t sleep; // 453 + uint16_t domoticz_switch_idx[MAX_DOMOTICZ_IDX]; // 454 + uint16_t domoticz_sensor_idx[12]; // 45C + uint8_t module; // 474 - // 3.9.7 - uint8_t ex_emulation; // Not used since 5.0.2 + uint8_t ws_color[4][3]; // 475 + uint8_t ws_width[3]; // 481 - // 3.9.20 - char web_password[33]; + myio my_gp; // 484 + uint16_t light_pixels; // 496 + uint8_t light_color[5]; // 498 + uint8_t light_correction; // 49D + uint8_t light_dimmer; // 49E - // 3.9.21 - uint8_t switchmode[4]; + byte free_49F[2]; // 49F - // 4.0.4 - char ntp_server[3][33]; - uint16_t pulsetime[MAX_PULSETIMERS]; + uint8_t light_fade; // 4A1 + uint8_t light_speed; // 4A2 + uint8_t light_scheme; // 4A3 + uint8_t light_width; // 4A4 - // 4.0.7 - uint16_t pwmvalue[5]; + byte free_4A5[1]; // 4A5 - // 4.0.9 - uint32_t ip_address[4]; + uint16_t light_wakeup; // 4A6 - // 5.0.4 - unsigned long hlw_kWhtotal; + byte free_4A8[1]; // 4A8 - // 5.0.4a - char mqtt_fulltopic[101]; + char web_password[33]; // 4A9 + uint8_t switchmode[MAX_SWITCHES]; // 4CA + char ntp_server[3][33]; // 4CE - // 5.1.1 - unsigned long pCounter[MAX_COUNTERS]; - uint16_t pCounterType; - uint16_t pCounterDebounce; + byte free_531[1]; // 531 - // 5.4.1 - uint8_t sfb_code[17][9]; + uint16_t pulse_timer[MAX_PULSETIMERS]; // 532 -} sysCfg; + byte free_542[2]; // 542 + + uint32_t ip_address[4]; // 544 + unsigned long hlw_kWhtotal; // 554 + char mqtt_fulltopic[101]; // 558 + + byte free_5BD[3]; // 5BD + + unsigned long pulse_counter[MAX_COUNTERS]; // 5C0 + uint16_t pulse_counter_type; // 5D0 + uint16_t pulse_counter_debounce; // 5D2 + uint8_t rf_code[17][9]; // 5D4 + +} Settings; struct RTCMEM { - uint16_t valid; - byte osw_flag; - uint8_t power; - unsigned long hlw_kWhtoday; - unsigned long hlw_kWhtotal; - unsigned long pCounter[MAX_COUNTERS]; -} rtcMem; + uint16_t valid; // 000 + byte oswatch_blocked_loop; // 002 + uint8_t unused; // 003 + unsigned long hlw_kWhtoday; // 004 + unsigned long hlw_kWhtotal; // 008 + unsigned long pulse_counter[MAX_COUNTERS]; // 00C + power_t power; // 01C +} RtcSettings; + +struct TIME_T { + uint8_t second; + uint8_t minute; + uint8_t hour; + uint8_t day_of_week; // sunday is day 1 + uint8_t day_of_month; + uint8_t month; + char name_of_month[4]; + uint16_t day_of_year; + uint16_t year; + unsigned long valid; +} RtcTime; + +struct TimeChangeRule +{ + uint8_t hemis; // 0-Northern, 1=Southern Hemisphere (=Opposite DST/STD) + uint8_t week; // 1=First, 2=Second, 3=Third, 4=Fourth, or 0=Last week of the month + uint8_t dow; // day of week, 1=Sun, 2=Mon, ... 7=Sat + uint8_t month; // 1=Jan, 2=Feb, ... 12=Dec + uint8_t hour; // 0-23 + int offset; // offset from UTC in minutes +}; + +TimeChangeRule DaylightSavingTime = { TIME_DST }; // Daylight Saving Time +TimeChangeRule StandardTime = { TIME_STD }; // Standard Time // See issue https://github.com/esp8266/Arduino/issues/2913 #ifdef USE_ADC_VCC ADC_MODE(ADC_VCC); // Set ADC input for Power Supply Voltage usage #endif + +#endif // _SETTINGS_H_ \ No newline at end of file diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 1c8e4d4eb..3c0607873 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -17,7 +17,9 @@ along with this program. If not, see . */ -const uint8_t sfb_codeDefault[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; +#ifndef DOMOTICZ_UPDATE_TIMER +#define DOMOTICZ_UPDATE_TIMER 0 // [DomoticzUpdateTimer] Send relay status (0 = disable, 1 - 3600 seconds) (Optional) +#endif /*********************************************************************************************\ * RTC memory @@ -25,12 +27,12 @@ const uint8_t sfb_codeDefault[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, #define RTC_MEM_VALID 0xA55A -uint32_t _rtcHash = 0; +uint32_t rtc_settings_hash = 0; -uint32_t getRtcHash() +uint32_t GetRtcSettingsHash() { uint32_t hash = 0; - uint8_t *bytes = (uint8_t*)&rtcMem; + uint8_t *bytes = (uint8_t*)&RtcSettings; for (uint16_t i = 0; i < sizeof(RTCMEM); i++) { hash += bytes[i]*(i+1); @@ -38,47 +40,47 @@ uint32_t getRtcHash() return hash; } -void RTC_Save() +void RtcSettingsSave() { - if (getRtcHash() != _rtcHash) { - rtcMem.valid = RTC_MEM_VALID; - ESP.rtcUserMemoryWrite(100, (uint32_t*)&rtcMem, sizeof(RTCMEM)); - _rtcHash = getRtcHash(); + if (GetRtcSettingsHash() != rtc_settings_hash) { + RtcSettings.valid = RTC_MEM_VALID; + ESP.rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); + rtc_settings_hash = GetRtcSettingsHash(); #ifdef DEBUG_THEO - addLog_P(LOG_LEVEL_DEBUG, PSTR("Dump: Save")); - RTC_Dump(); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("Dump: Save")); + RtcSettingsDump(); #endif // DEBUG_THEO } } -void RTC_Load() +void RtcSettingsLoad() { - ESP.rtcUserMemoryRead(100, (uint32_t*)&rtcMem, sizeof(RTCMEM)); + ESP.rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); #ifdef DEBUG_THEO - addLog_P(LOG_LEVEL_DEBUG, PSTR("Dump: Load")); - RTC_Dump(); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("Dump: Load")); + RtcSettingsDump(); #endif // DEBUG_THEO - if (rtcMem.valid != RTC_MEM_VALID) { - memset(&rtcMem, 0x00, sizeof(RTCMEM)); - rtcMem.valid = RTC_MEM_VALID; - rtcMem.power = sysCfg.power; - rtcMem.hlw_kWhtoday = sysCfg.hlw_kWhtoday; - rtcMem.hlw_kWhtotal = sysCfg.hlw_kWhtotal; - for (byte i = 0; i < 4; i++) { - rtcMem.pCounter[i] = sysCfg.pCounter[i]; + if (RtcSettings.valid != RTC_MEM_VALID) { + memset(&RtcSettings, 0, sizeof(RTCMEM)); + RtcSettings.valid = RTC_MEM_VALID; + RtcSettings.hlw_kWhtoday = Settings.hlw_kWhtoday; + RtcSettings.hlw_kWhtotal = Settings.hlw_kWhtotal; + for (byte i = 0; i < MAX_COUNTERS; i++) { + RtcSettings.pulse_counter[i] = Settings.pulse_counter[i]; } - RTC_Save(); + RtcSettings.power = Settings.power; + RtcSettingsSave(); } - _rtcHash = getRtcHash(); + rtc_settings_hash = GetRtcSettingsHash(); } -boolean RTC_Valid() +boolean RtcSettingsValid() { - return (RTC_MEM_VALID == rtcMem.valid); + return (RTC_MEM_VALID == RtcSettings.valid); } #ifdef DEBUG_THEO -void RTC_Dump() +void RtcSettingsDump() { #define CFG_COLS 16 @@ -87,7 +89,7 @@ void RTC_Dump() uint16_t row; uint16_t col; - uint8_t *buffer = (uint8_t *) &rtcMem; + uint8_t *buffer = (uint8_t *) &RtcSettings; maxrow = ((sizeof(RTCMEM)+CFG_COLS)/CFG_COLS); for (row = 0; row < maxrow; row++) { @@ -107,7 +109,7 @@ void RTC_Dump() snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); } snprintf_P(log_data, sizeof(log_data), PSTR("%s|"), log_data); - addLog(LOG_LEVEL_INFO); + AddLog(LOG_LEVEL_INFO); } } #endif // DEBUG_THEO @@ -126,21 +128,21 @@ extern "C" uint32_t _SPIFFS_end; #define SPIFFS_END ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE // Version 3.x config -#define CFG_LOCATION_3 SPIFFS_END - 4 +#define SETTINGS_LOCATION_3 SPIFFS_END - 4 // Version 4.2 config = eeprom area -#define CFG_LOCATION SPIFFS_END // No need for SPIFFS as it uses EEPROM area +#define SETTINGS_LOCATION SPIFFS_END // No need for SPIFFS as it uses EEPROM area // Version 5.2 allow for more flash space #define CFG_ROTATES 8 // Number of flash sectors used (handles uploads) -uint32_t _cfgHash = 0; -uint32_t _cfgLocation = CFG_LOCATION; +uint32_t settings_hash = 0; +uint32_t settings_location = SETTINGS_LOCATION; /********************************************************************************************/ /* * Based on cores/esp8266/Updater.cpp */ -void setFlashModeDout() +void SetFlashModeDout() { uint8_t *_buffer; uint32_t address; @@ -162,10 +164,10 @@ void setFlashModeDout() delete[] _buffer; } -uint32_t getHash() +uint32_t GetSettingsHash() { uint32_t hash = 0; - uint8_t *bytes = (uint8_t*)&sysCfg; + uint8_t *bytes = (uint8_t*)&Settings; for (uint16_t i = 0; i < sizeof(SYSCFG); i++) { hash += bytes[i]*(i+1); @@ -177,12 +179,12 @@ uint32_t getHash() * Config Save - Save parameters to Flash ONLY if any parameter has changed \*********************************************************************************************/ -uint32_t CFG_Address() +uint32_t GetSettingsAddress() { - return _cfgLocation * SPI_FLASH_SEC_SIZE; + return settings_location * SPI_FLASH_SEC_SIZE; } -void CFG_Save(byte rotate) +void SettingsSave(byte rotate) { /* Save configuration in eeprom or one of 7 slots below * @@ -193,90 +195,90 @@ void CFG_Save(byte rotate) * stop_flash_rotate 1 = Allow only eeprom flash slot use (SetOption12 1) */ #ifndef BE_MINIMAL - if ((getHash() != _cfgHash) || rotate) { + if ((GetSettingsHash() != settings_hash) || rotate) { if (1 == rotate) { // Use eeprom flash slot only and disable flash rotate from now on (upgrade) stop_flash_rotate = 1; } if (2 == rotate) { // Use eeprom flash slot and erase next flash slots if stop_flash_rotate is off (default) - _cfgLocation = CFG_LOCATION +1; + settings_location = SETTINGS_LOCATION +1; } if (stop_flash_rotate) { - _cfgLocation = CFG_LOCATION; + settings_location = SETTINGS_LOCATION; } else { - _cfgLocation--; - if (_cfgLocation <= (CFG_LOCATION - CFG_ROTATES)) { - _cfgLocation = CFG_LOCATION; + settings_location--; + if (settings_location <= (SETTINGS_LOCATION - CFG_ROTATES)) { + settings_location = SETTINGS_LOCATION; } } - sysCfg.saveFlag++; + Settings.save_flag++; noInterrupts(); - spi_flash_erase_sector(_cfgLocation); - spi_flash_write(_cfgLocation * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg, sizeof(SYSCFG)); + spi_flash_erase_sector(settings_location); + spi_flash_write(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); interrupts(); if (!stop_flash_rotate && rotate) { for (byte i = 1; i < CFG_ROTATES; i++) { noInterrupts(); - spi_flash_erase_sector(_cfgLocation -i); // Delete previous configurations by resetting to 0xFF + spi_flash_erase_sector(settings_location -i); // Delete previous configurations by resetting to 0xFF interrupts(); delay(1); } } snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), - _cfgLocation, sysCfg.saveFlag, sizeof(SYSCFG)); - addLog(LOG_LEVEL_DEBUG); - _cfgHash = getHash(); + settings_location, Settings.save_flag, sizeof(SYSCFG)); + AddLog(LOG_LEVEL_DEBUG); + settings_hash = GetSettingsHash(); } #endif // BE_MINIMAL - RTC_Save(); + RtcSettingsSave(); } -void CFG_Load() +void SettingsLoad() { /* Load configuration from eeprom or one of 7 slots below if first load does not stop_flash_rotate */ struct SYSCFGH { unsigned long cfg_holder; - unsigned long saveFlag; - } _sysCfgH; + unsigned long save_flag; + } _SettingsH; - _cfgLocation = CFG_LOCATION +1; + settings_location = SETTINGS_LOCATION +1; for (byte i = 0; i < CFG_ROTATES; i++) { - _cfgLocation--; + settings_location--; noInterrupts(); - spi_flash_read(_cfgLocation * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg, sizeof(SYSCFG)); - spi_flash_read((_cfgLocation -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_sysCfgH, sizeof(SYSCFGH)); + spi_flash_read(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + spi_flash_read((settings_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH)); interrupts(); -// snprintf_P(log_data, sizeof(log_data), PSTR("Cnfg: Check at %X with count %d and holder %X"), _cfgLocation -1, _sysCfgH.saveFlag, _sysCfgH.cfg_holder); -// addLog(LOG_LEVEL_DEBUG); +// snprintf_P(log_data, sizeof(log_data), PSTR("Cnfg: Check at %X with count %d and holder %X"), settings_location -1, _SettingsH.save_flag, _SettingsH.cfg_holder); +// AddLog(LOG_LEVEL_DEBUG); - if (((sysCfg.version > 0x05000200) && sysCfg.flag.stop_flash_rotate) || (sysCfg.cfg_holder != _sysCfgH.cfg_holder) || (sysCfg.saveFlag > _sysCfgH.saveFlag)) { + if (((Settings.version > 0x05000200) && Settings.flag.stop_flash_rotate) || (Settings.cfg_holder != _SettingsH.cfg_holder) || (Settings.save_flag > _SettingsH.save_flag)) { break; } delay(1); } snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %d"), - _cfgLocation, sysCfg.saveFlag); - addLog(LOG_LEVEL_DEBUG); - if (sysCfg.cfg_holder != CFG_HOLDER) { + settings_location, Settings.save_flag); + AddLog(LOG_LEVEL_DEBUG); + if (Settings.cfg_holder != CFG_HOLDER) { // Auto upgrade noInterrupts(); - spi_flash_read((CFG_LOCATION_3) * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg, sizeof(SYSCFG)); - spi_flash_read((CFG_LOCATION_3 + 1) * SPI_FLASH_SEC_SIZE, (uint32*)&_sysCfgH, sizeof(SYSCFGH)); - if (sysCfg.saveFlag < _sysCfgH.saveFlag) - spi_flash_read((CFG_LOCATION_3 + 1) * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg, sizeof(SYSCFG)); + spi_flash_read((SETTINGS_LOCATION_3) * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + spi_flash_read((SETTINGS_LOCATION_3 + 1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH)); + if (Settings.save_flag < _SettingsH.save_flag) + spi_flash_read((SETTINGS_LOCATION_3 + 1) * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); interrupts(); - if ((sysCfg.cfg_holder != CFG_HOLDER) || (sysCfg.version >= 0x04020000)) { - CFG_Default(); + if ((Settings.cfg_holder != CFG_HOLDER) || (Settings.version >= 0x04020000)) { + SettingsDefault(); } } - _cfgHash = getHash(); + settings_hash = GetSettingsHash(); - RTC_Load(); + RtcSettingsLoad(); } -void CFG_Erase() +void SettingsErase() { SpiFlashOpResult result; @@ -285,7 +287,7 @@ void CFG_Erase() boolean _serialoutput = (LOG_LEVEL_DEBUG_MORE <= seriallog_level); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_ERASE " %d " D_UNIT_SECTORS), _sectorEnd - _sectorStart); - addLog(LOG_LEVEL_DEBUG); + AddLog(LOG_LEVEL_DEBUG); for (uint32_t _sector = _sectorStart; _sector < _sectorEnd; _sector++) { noInterrupts(); @@ -301,10 +303,11 @@ void CFG_Erase() } delay(10); } + OsWatchLoop(); } } -void CFG_Dump(char* parms) +void SettingsDump(char* parms) { #define CFG_COLS 16 @@ -314,14 +317,14 @@ void CFG_Dump(char* parms) uint16_t col; char *p; - uint8_t *buffer = (uint8_t *) &sysCfg; + uint8_t *buffer = (uint8_t *) &Settings; maxrow = ((sizeof(SYSCFG)+CFG_COLS)/CFG_COLS); uint16_t srow = strtol(parms, &p, 16) / CFG_COLS; uint16_t mrow = strtol(p, &p, 10); // snprintf_P(log_data, sizeof(log_data), PSTR("Cnfg: Parms %s, Start row %d, rows %d"), parms, srow, mrow); -// addLog(LOG_LEVEL_DEBUG); +// AddLog(LOG_LEVEL_DEBUG); if (0 == mrow) { // Default only 8 lines mrow = 8; @@ -350,393 +353,429 @@ void CFG_Dump(char* parms) snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); } snprintf_P(log_data, sizeof(log_data), PSTR("%s|"), log_data); - addLog(LOG_LEVEL_INFO); + AddLog(LOG_LEVEL_INFO); delay(1); } } /********************************************************************************************/ -void CFG_Default() +void SettingsDefault() { - addLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_USE_DEFAULTS)); - CFG_DefaultSet1(); - CFG_DefaultSet2(); - CFG_Save(2); + AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_USE_DEFAULTS)); + SettingsDefaultSet1(); + SettingsDefaultSet2(); + SettingsSave(2); } -void CFG_DefaultSet1() +void SettingsDefaultSet1() { - memset(&sysCfg, 0x00, sizeof(SYSCFG)); + memset(&Settings, 0x00, sizeof(SYSCFG)); - sysCfg.cfg_holder = CFG_HOLDER; -// sysCfg.saveFlag = 0; - sysCfg.version = VERSION; -// sysCfg.bootcount = 0; + Settings.cfg_holder = CFG_HOLDER; +// Settings.save_flag = 0; + Settings.version = VERSION; +// Settings.bootcount = 0; } -void CFG_DefaultSet2() +void SettingsDefaultSet2() { - memset((char*)&sysCfg +16, 0x00, sizeof(SYSCFG) -16); + memset((char*)&Settings +16, 0x00, sizeof(SYSCFG) -16); - sysCfg.flag.savestate = SAVE_STATE; - sysCfg.savedata = SAVE_DATA; - sysCfg.timezone = APP_TIMEZONE; - strlcpy(sysCfg.otaUrl, OTA_URL, sizeof(sysCfg.otaUrl)); + Settings.flag.save_state = SAVE_STATE; + //Settings.flag.button_restrict = 0; + //Settings.flag.value_units = 0; + Settings.flag.mqtt_enabled = MQTT_USE; + //Settings.flag.mqtt_response = 0; + Settings.flag.mqtt_power_retain = MQTT_POWER_RETAIN; + Settings.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN; + Settings.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN; - sysCfg.seriallog_level = SERIAL_LOG_LEVEL; -// sysCfg.sta_active = 0; - strlcpy(sysCfg.sta_ssid[0], STA_SSID1, sizeof(sysCfg.sta_ssid[0])); - strlcpy(sysCfg.sta_pwd[0], STA_PASS1, sizeof(sysCfg.sta_pwd[0])); - strlcpy(sysCfg.sta_ssid[1], STA_SSID2, sizeof(sysCfg.sta_ssid[1])); - strlcpy(sysCfg.sta_pwd[1], STA_PASS2, sizeof(sysCfg.sta_pwd[1])); - strlcpy(sysCfg.hostname, WIFI_HOSTNAME, sizeof(sysCfg.hostname)); - sysCfg.sta_config = WIFI_CONFIG_TOOL; - strlcpy(sysCfg.syslog_host, SYS_LOG_HOST, sizeof(sysCfg.syslog_host)); - sysCfg.syslog_port = SYS_LOG_PORT; - sysCfg.syslog_level = SYS_LOG_LEVEL; - sysCfg.webserver = WEB_SERVER; - sysCfg.weblog_level = WEB_LOG_LEVEL; + Settings.flag.emulation = EMULATION; - strlcpy(sysCfg.mqtt_fingerprint, MQTT_FINGERPRINT, sizeof(sysCfg.mqtt_fingerprint)); - strlcpy(sysCfg.mqtt_host, MQTT_HOST, sizeof(sysCfg.mqtt_host)); - sysCfg.mqtt_port = MQTT_PORT; - strlcpy(sysCfg.mqtt_client, MQTT_CLIENT_ID, sizeof(sysCfg.mqtt_client)); - strlcpy(sysCfg.mqtt_user, MQTT_USER, sizeof(sysCfg.mqtt_user)); - strlcpy(sysCfg.mqtt_pwd, MQTT_PASS, sizeof(sysCfg.mqtt_pwd)); - strlcpy(sysCfg.mqtt_topic, MQTT_TOPIC, sizeof(sysCfg.mqtt_topic)); - strlcpy(sysCfg.button_topic, "0", sizeof(sysCfg.button_topic)); - strlcpy(sysCfg.mqtt_grptopic, MQTT_GRPTOPIC, sizeof(sysCfg.mqtt_grptopic)); - sysCfg.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN; - sysCfg.flag.mqtt_power_retain = MQTT_POWER_RETAIN; -// sysCfg.flag.value_units = 0; -// sysCfg.flag.button_restrict = 0; - sysCfg.tele_period = TELE_PERIOD; + Settings.save_data = SAVE_DATA; + Settings.timezone = APP_TIMEZONE; + strlcpy(Settings.ota_url, OTA_URL, sizeof(Settings.ota_url)); - sysCfg.power = APP_POWER; - sysCfg.poweronstate = APP_POWERON_STATE; - sysCfg.ledstate = APP_LEDSTATE; - sysCfg.blinktime = APP_BLINKTIME; - sysCfg.blinkcount = APP_BLINKCOUNT; - sysCfg.sleep = APP_SLEEP; + Settings.seriallog_level = SERIAL_LOG_LEVEL; +// Settings.sta_active = 0; + strlcpy(Settings.sta_ssid[0], STA_SSID1, sizeof(Settings.sta_ssid[0])); + strlcpy(Settings.sta_pwd[0], STA_PASS1, sizeof(Settings.sta_pwd[0])); + strlcpy(Settings.sta_ssid[1], STA_SSID2, sizeof(Settings.sta_ssid[1])); + strlcpy(Settings.sta_pwd[1], STA_PASS2, sizeof(Settings.sta_pwd[1])); + strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); + Settings.sta_config = WIFI_CONFIG_TOOL; + strlcpy(Settings.syslog_host, SYS_LOG_HOST, sizeof(Settings.syslog_host)); + Settings.syslog_port = SYS_LOG_PORT; + Settings.syslog_level = SYS_LOG_LEVEL; + Settings.webserver = WEB_SERVER; + Settings.weblog_level = WEB_LOG_LEVEL; - sysCfg.domoticz_update_timer = DOMOTICZ_UPDATE_TIMER; - for (byte i = 0; i < 4; i++) { - sysCfg.switchmode[i] = SWITCH_MODE; -// sysCfg.domoticz_relay_idx[i] = 0; -// sysCfg.domoticz_key_idx[i] = 0; -// sysCfg.domoticz_switch_idx[i] = 0; + strlcpy(Settings.mqtt_fingerprint, MQTT_FINGERPRINT, sizeof(Settings.mqtt_fingerprint)); + strlcpy(Settings.mqtt_host, MQTT_HOST, sizeof(Settings.mqtt_host)); + Settings.mqtt_port = MQTT_PORT; + strlcpy(Settings.mqtt_client, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)); + strlcpy(Settings.mqtt_user, MQTT_USER, sizeof(Settings.mqtt_user)); + strlcpy(Settings.mqtt_pwd, MQTT_PASS, sizeof(Settings.mqtt_pwd)); + strlcpy(Settings.mqtt_topic, MQTT_TOPIC, sizeof(Settings.mqtt_topic)); + strlcpy(Settings.button_topic, "0", sizeof(Settings.button_topic)); + strlcpy(Settings.mqtt_grptopic, MQTT_GRPTOPIC, sizeof(Settings.mqtt_grptopic)); + Settings.tele_period = TELE_PERIOD; + + Settings.power = APP_POWER; + Settings.poweronstate = APP_POWERON_STATE; + Settings.ledstate = APP_LEDSTATE; + Settings.blinktime = APP_BLINKTIME; + Settings.blinkcount = APP_BLINKCOUNT; + Settings.sleep = APP_SLEEP; + + Settings.domoticz_update_timer = DOMOTICZ_UPDATE_TIMER; + for (byte i = 0; i < MAX_SWITCHES; i++) { + Settings.switchmode[i] = SWITCH_MODE; +// Settings.domoticz_relay_idx[i] = 0; +// Settings.domoticz_key_idx[i] = 0; +// Settings.domoticz_switch_idx[i] = 0; } - sysCfg.hlw_pcal = HLW_PREF_PULSE; - sysCfg.hlw_ucal = HLW_UREF_PULSE; - sysCfg.hlw_ical = HLW_IREF_PULSE; -// sysCfg.hlw_kWhtoday = 0; -// sysCfg.hlw_kWhyesterday = 0; -// sysCfg.hlw_kWhdoy = 0; -// sysCfg.hlw_pmin = 0; -// sysCfg.hlw_pmax = 0; -// sysCfg.hlw_umin = 0; -// sysCfg.hlw_umax = 0; -// sysCfg.hlw_imin = 0; -// sysCfg.hlw_imax = 0; -// sysCfg.hlw_mpl = 0; // MaxPowerLimit - sysCfg.hlw_mplh = MAX_POWER_HOLD; - sysCfg.hlw_mplw = MAX_POWER_WINDOW; -// sysCfg.hlw_mspl = 0; // MaxSafePowerLimit - sysCfg.hlw_msplh = SAFE_POWER_HOLD; - sysCfg.hlw_msplw = SAFE_POWER_WINDOW; -// sysCfg.hlw_mkwh = 0; // MaxEnergy -// sysCfg.hlw_mkwhs = 0; // MaxEnergyStart + Settings.hlw_power_calibration = HLW_PREF_PULSE; + Settings.hlw_voltage_calibration = HLW_UREF_PULSE; + Settings.hlw_current_calibration = HLW_IREF_PULSE; +// Settings.hlw_kWhtoday = 0; +// Settings.hlw_kWhyesterday = 0; +// Settings.hlw_kWhdoy = 0; +// Settings.hlw_pmin = 0; +// Settings.hlw_pmax = 0; +// Settings.hlw_umin = 0; +// Settings.hlw_umax = 0; +// Settings.hlw_imin = 0; +// Settings.hlw_imax = 0; +// Settings.hlw_mpl = 0; // MaxPowerLimit + Settings.hlw_mplh = MAX_POWER_HOLD; + Settings.hlw_mplw = MAX_POWER_WINDOW; +// Settings.hlw_mspl = 0; // MaxSafePowerLimit + Settings.hlw_msplh = SAFE_POWER_HOLD; + Settings.hlw_msplw = SAFE_POWER_WINDOW; +// Settings.hlw_mkwh = 0; // MaxEnergy +// Settings.hlw_mkwhs = 0; // MaxEnergyStart - CFG_DefaultSet_3_2_4(); + SettingsDefaultSet_3_2_4(); - strlcpy(sysCfg.friendlyname[0], FRIENDLY_NAME, sizeof(sysCfg.friendlyname[0])); - strlcpy(sysCfg.friendlyname[1], FRIENDLY_NAME"2", sizeof(sysCfg.friendlyname[1])); - strlcpy(sysCfg.friendlyname[2], FRIENDLY_NAME"3", sizeof(sysCfg.friendlyname[2])); - strlcpy(sysCfg.friendlyname[3], FRIENDLY_NAME"4", sizeof(sysCfg.friendlyname[3])); + strlcpy(Settings.friendlyname[0], FRIENDLY_NAME, sizeof(Settings.friendlyname[0])); + strlcpy(Settings.friendlyname[1], FRIENDLY_NAME"2", sizeof(Settings.friendlyname[1])); + strlcpy(Settings.friendlyname[2], FRIENDLY_NAME"3", sizeof(Settings.friendlyname[2])); + strlcpy(Settings.friendlyname[3], FRIENDLY_NAME"4", sizeof(Settings.friendlyname[3])); - CFG_DefaultSet_3_9_3(); + SettingsDefaultSet_3_9_3(); - strlcpy(sysCfg.switch_topic, "0", sizeof(sysCfg.switch_topic)); - sysCfg.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN; - sysCfg.flag.mqtt_enabled = MQTT_USE; + strlcpy(Settings.switch_topic, "0", sizeof(Settings.switch_topic)); - sysCfg.flag.emulation = EMULATION; + strlcpy(Settings.web_password, WEB_PASSWORD, sizeof(Settings.web_password)); - strlcpy(sysCfg.web_password, WEB_PASSWORD, sizeof(sysCfg.web_password)); - - CFG_DefaultSet_4_0_4(); - sysCfg.pulsetime[0] = APP_PULSETIME; + SettingsDefaultSet_4_0_4(); + Settings.pulse_timer[0] = APP_PULSETIME; // 4.0.7 -// for (byte i = 0; i < 5; i++) sysCfg.pwmvalue[i] = 0; +// for (byte i = 0; i < MAX_PWMS; i++) Settings.pwm_value[i] = 0; // 4.0.9 - CFG_DefaultSet_4_0_9(); + SettingsDefaultSet_4_0_9(); // 4.1.1 + 5.1.6 - CFG_DefaultSet_4_1_1(); + SettingsDefaultSet_4_1_1(); // 5.0.2 - CFG_DefaultSet_5_0_2(); + SettingsDefaultSet_5_0_2(); // 5.0.4 -// sysCfg.hlw_kWhtotal = 0; - rtcMem.hlw_kWhtotal = 0; +// Settings.hlw_kWhtotal = 0; + RtcSettings.hlw_kWhtotal = 0; // 5.0.5 - strlcpy(sysCfg.mqtt_fulltopic, MQTT_FULLTOPIC, sizeof(sysCfg.mqtt_fulltopic)); + strlcpy(Settings.mqtt_fulltopic, MQTT_FULLTOPIC, sizeof(Settings.mqtt_fulltopic)); // 5.0.6 - sysCfg.mqtt_retry = MQTT_RETRY_SECS; + Settings.mqtt_retry = MQTT_RETRY_SECS; // 5.1.7 - sysCfg.param[P_HOLD_TIME] = KEY_HOLD_TIME; // Default 4 seconds hold time + Settings.param[P_HOLD_TIME] = KEY_HOLD_TIME; // Default 4 seconds hold time // 5.2.0 - sysCfg.param[P_MAX_POWER_RETRY] = MAX_POWER_RETRY; + Settings.param[P_MAX_POWER_RETRY] = MAX_POWER_RETRY; // 5.4.1 - memcpy_P(sysCfg.sfb_code[0], sfb_codeDefault, 9); + memcpy_P(Settings.rf_code[0], kDefaultRfCode, 9); // 5.8.0 - sysCfg.led_pixels = 1; + Settings.light_pixels = WS2812_LEDS; + + // 5.8.1 +// Settings.altitude = 0; + Settings.pwm_frequency = PWM_FREQ; + Settings.pwm_range = PWM_RANGE; + SettingsDefaultSet_5_8_1(); } /********************************************************************************************/ -void CFG_DefaultSet_3_2_4() +void SettingsDefaultSet_3_2_4() { - sysCfg.ws_pixels = WS2812_LEDS; - sysCfg.ws_red = 255; - sysCfg.ws_green = 0; - sysCfg.ws_blue = 0; - sysCfg.ws_ledtable = 0; - sysCfg.ws_dimmer = 8; - sysCfg.ws_fade = 0; - sysCfg.ws_speed = 1; - sysCfg.ws_scheme = 0; - sysCfg.ws_width = 1; - sysCfg.ws_wakeup = 0; + Settings.ws_pixels = WS2812_LEDS; + Settings.ws_red = 255; + Settings.ws_green = 0; + Settings.ws_blue = 0; + Settings.ws_ledtable = 0; + Settings.ws_dimmer = 8; + Settings.ws_fade = 0; + Settings.ws_speed = 1; + Settings.ws_scheme = 0; + Settings.ex_ws_width = 1; + Settings.ws_wakeup = 0; } -void CFG_DefaultSet_3_9_3() +void SettingsDefaultSet_3_9_3() { - for (byte i = 0; i < 4; i++) { - sysCfg.domoticz_switch_idx[i] = 0; + for (byte i = 0; i < MAX_DOMOTICZ_IDX; i++) { + Settings.domoticz_switch_idx[i] = 0; } for (byte i = 0; i < 12; i++) { - sysCfg.domoticz_sensor_idx[i] = 0; + Settings.domoticz_sensor_idx[i] = 0; } - sysCfg.module = MODULE; + Settings.module = MODULE; for (byte i = 0; i < MAX_GPIO_PIN; i++){ - sysCfg.my_module.gp.io[i] = 0; + Settings.my_gp.io[i] = 0; } - sysCfg.led_pixels = WS2812_LEDS; - for (byte i = 0; i < 5; i++) { - sysCfg.led_color[i] = 255; + Settings.light_pixels = WS2812_LEDS; + for (byte i = 0; i < MAX_PWMS; i++) { + Settings.light_color[i] = 255; } - sysCfg.led_table = 0; - for (byte i = 0; i < 3; i++){ - sysCfg.led_dimmer[i] = 10; - } - sysCfg.led_fade = 0; - sysCfg.led_speed = 1; - sysCfg.led_scheme = 0; - sysCfg.led_width = 1; - sysCfg.led_wakeup = 0; + Settings.light_correction = 0; + Settings.light_dimmer = 10; + Settings.light_fade = 0; + Settings.light_speed = 1; + Settings.light_scheme = 0; + Settings.light_width = 1; + Settings.light_wakeup = 0; } -void CFG_DefaultSet_4_0_4() +void SettingsDefaultSet_4_0_4() { - strlcpy(sysCfg.ntp_server[0], NTP_SERVER1, sizeof(sysCfg.ntp_server[0])); - strlcpy(sysCfg.ntp_server[1], NTP_SERVER2, sizeof(sysCfg.ntp_server[1])); - strlcpy(sysCfg.ntp_server[2], NTP_SERVER3, sizeof(sysCfg.ntp_server[2])); - for (byte j =0; j < 3; j++) { - for (byte i = 0; i < strlen(sysCfg.ntp_server[j]); i++) { - if (sysCfg.ntp_server[j][i] == ',') { - sysCfg.ntp_server[j][i] = '.'; + strlcpy(Settings.ntp_server[0], NTP_SERVER1, sizeof(Settings.ntp_server[0])); + strlcpy(Settings.ntp_server[1], NTP_SERVER2, sizeof(Settings.ntp_server[1])); + strlcpy(Settings.ntp_server[2], NTP_SERVER3, sizeof(Settings.ntp_server[2])); + for (byte j = 0; j < 3; j++) { + for (byte i = 0; i < strlen(Settings.ntp_server[j]); i++) { + if (Settings.ntp_server[j][i] == ',') { + Settings.ntp_server[j][i] = '.'; } } } - sysCfg.pulsetime[0] = APP_PULSETIME; + Settings.pulse_timer[0] = APP_PULSETIME; for (byte i = 1; i < MAX_PULSETIMERS; i++) { - sysCfg.pulsetime[i] = 0; + Settings.pulse_timer[i] = 0; } } -void CFG_DefaultSet_4_0_9() +void SettingsDefaultSet_4_0_9() { - strlcpy(sysCfg.mqtt_prefix[0], SUB_PREFIX, sizeof(sysCfg.mqtt_prefix[0])); - strlcpy(sysCfg.mqtt_prefix[1], PUB_PREFIX, sizeof(sysCfg.mqtt_prefix[1])); - strlcpy(sysCfg.mqtt_prefix[2], PUB_PREFIX2, sizeof(sysCfg.mqtt_prefix[2])); - parseIP(&sysCfg.ip_address[0], WIFI_IP_ADDRESS); - parseIP(&sysCfg.ip_address[1], WIFI_GATEWAY); - parseIP(&sysCfg.ip_address[2], WIFI_SUBNETMASK); - parseIP(&sysCfg.ip_address[3], WIFI_DNS); + strlcpy(Settings.mqtt_prefix[0], SUB_PREFIX, sizeof(Settings.mqtt_prefix[0])); + strlcpy(Settings.mqtt_prefix[1], PUB_PREFIX, sizeof(Settings.mqtt_prefix[1])); + strlcpy(Settings.mqtt_prefix[2], PUB_PREFIX2, sizeof(Settings.mqtt_prefix[2])); + ParseIp(&Settings.ip_address[0], WIFI_IP_ADDRESS); + ParseIp(&Settings.ip_address[1], WIFI_GATEWAY); + ParseIp(&Settings.ip_address[2], WIFI_SUBNETMASK); + ParseIp(&Settings.ip_address[3], WIFI_DNS); } -void CFG_DefaultSet_4_1_1() +void SettingsDefaultSet_4_1_1() { - strlcpy(sysCfg.state_text[0], MQTT_STATUS_OFF, sizeof(sysCfg.state_text[0])); - strlcpy(sysCfg.state_text[1], MQTT_STATUS_ON, sizeof(sysCfg.state_text[1])); - strlcpy(sysCfg.state_text[2], MQTT_CMND_TOGGLE, sizeof(sysCfg.state_text[2])); - strlcpy(sysCfg.state_text[3], MQTT_CMND_HOLD, sizeof(sysCfg.state_text[3])); // v5.1.6 + strlcpy(Settings.state_text[0], MQTT_STATUS_OFF, sizeof(Settings.state_text[0])); + strlcpy(Settings.state_text[1], MQTT_STATUS_ON, sizeof(Settings.state_text[1])); + strlcpy(Settings.state_text[2], MQTT_CMND_TOGGLE, sizeof(Settings.state_text[2])); + strlcpy(Settings.state_text[3], MQTT_CMND_HOLD, sizeof(Settings.state_text[3])); // v5.1.6 } -void CFG_DefaultSet_5_0_2() +void SettingsDefaultSet_5_0_2() { - sysCfg.flag.temperature_conversion = TEMP_CONVERSION; - sysCfg.flag.temperature_resolution = TEMP_RESOLUTION; - sysCfg.flag.humidity_resolution = HUMIDITY_RESOLUTION; - sysCfg.flag.pressure_resolution = PRESSURE_RESOLUTION; - sysCfg.flag.energy_resolution = ENERGY_RESOLUTION; + Settings.flag.temperature_conversion = TEMP_CONVERSION; + Settings.flag.temperature_resolution = TEMP_RESOLUTION; + Settings.flag.humidity_resolution = HUMIDITY_RESOLUTION; + Settings.flag.pressure_resolution = PRESSURE_RESOLUTION; + Settings.flag.energy_resolution = ENERGY_RESOLUTION; +} + +void SettingsDefaultSet_5_8_1() +{ +// Settings.flag.ws_clock_reverse = 0; + Settings.ws_width[WS_SECOND] = 1; + Settings.ws_color[WS_SECOND][WS_RED] = 255; + Settings.ws_color[WS_SECOND][WS_GREEN] = 0; + Settings.ws_color[WS_SECOND][WS_BLUE] = 255; + Settings.ws_width[WS_MINUTE] = 3; + Settings.ws_color[WS_MINUTE][WS_RED] = 0; + Settings.ws_color[WS_MINUTE][WS_GREEN] = 255; + Settings.ws_color[WS_MINUTE][WS_BLUE] = 0; + Settings.ws_width[WS_HOUR] = 5; + Settings.ws_color[WS_HOUR][WS_RED] = 255; + Settings.ws_color[WS_HOUR][WS_GREEN] = 0; + Settings.ws_color[WS_HOUR][WS_BLUE] = 0; } /********************************************************************************************/ -void CFG_Delta() +void SettingsDelta() { - if (sysCfg.version != VERSION) { // Fix version dependent changes - if (sysCfg.version < 0x03010200) { // 3.1.2 - Add parameter - sysCfg.poweronstate = APP_POWERON_STATE; + if (Settings.version != VERSION) { // Fix version dependent changes + if (Settings.version < 0x03010200) { // 3.1.2 - Add parameter + Settings.poweronstate = APP_POWERON_STATE; } - if (sysCfg.version < 0x03010600) { // 3.1.6 - Add parameter - sysCfg.blinktime = APP_BLINKTIME; - sysCfg.blinkcount = APP_BLINKCOUNT; + if (Settings.version < 0x03010600) { // 3.1.6 - Add parameter + Settings.blinktime = APP_BLINKTIME; + Settings.blinkcount = APP_BLINKCOUNT; } - if (sysCfg.version < 0x03020400) { // 3.2.4 - Add parameter - CFG_DefaultSet_3_2_4(); + if (Settings.version < 0x03020400) { // 3.2.4 - Add parameter + SettingsDefaultSet_3_2_4(); } - if (sysCfg.version < 0x03020500) { // 3.2.5 - Add parameter - getClient(sysCfg.friendlyname[0], sysCfg.mqtt_client, sizeof(sysCfg.friendlyname[0])); - strlcpy(sysCfg.friendlyname[1], FRIENDLY_NAME"2", sizeof(sysCfg.friendlyname[1])); - strlcpy(sysCfg.friendlyname[2], FRIENDLY_NAME"3", sizeof(sysCfg.friendlyname[2])); - strlcpy(sysCfg.friendlyname[3], FRIENDLY_NAME"4", sizeof(sysCfg.friendlyname[3])); + if (Settings.version < 0x03020500) { // 3.2.5 - Add parameter + GetMqttClient(Settings.friendlyname[0], Settings.mqtt_client, sizeof(Settings.friendlyname[0])); + strlcpy(Settings.friendlyname[1], FRIENDLY_NAME"2", sizeof(Settings.friendlyname[1])); + strlcpy(Settings.friendlyname[2], FRIENDLY_NAME"3", sizeof(Settings.friendlyname[2])); + strlcpy(Settings.friendlyname[3], FRIENDLY_NAME"4", sizeof(Settings.friendlyname[3])); } - if (sysCfg.version < 0x03020800) { // 3.2.8 - Add parameter - strlcpy(sysCfg.switch_topic, sysCfg.button_topic, sizeof(sysCfg.switch_topic)); - sysCfg.ex_mqtt_switch_retain = MQTT_SWITCH_RETAIN; - sysCfg.ex_mqtt_enabled = MQTT_USE; + if (Settings.version < 0x03020800) { // 3.2.8 - Add parameter + strlcpy(Settings.switch_topic, Settings.button_topic, sizeof(Settings.switch_topic)); } - if (sysCfg.version < 0x03020C00) { // 3.2.12 - Add parameter - sysCfg.sleep = APP_SLEEP; + if (Settings.version < 0x03020C00) { // 3.2.12 - Add parameter + Settings.sleep = APP_SLEEP; } - if (sysCfg.version < 0x03090300) { // 3.9.2d - Add parameter - CFG_DefaultSet_3_9_3(); + if (Settings.version < 0x03090300) { // 3.9.2d - Add parameter + SettingsDefaultSet_3_9_3(); } - if (sysCfg.version < 0x03090700) { // 3.9.7 - Add parameter - sysCfg.ex_emulation = EMULATION; + if (Settings.version < 0x03091400) { + strlcpy(Settings.web_password, WEB_PASSWORD, sizeof(Settings.web_password)); } - if (sysCfg.version < 0x03091400) { - strlcpy(sysCfg.web_password, WEB_PASSWORD, sizeof(sysCfg.web_password)); - } - if (sysCfg.version < 0x03091500) { - for (byte i = 0; i < 4; i++) sysCfg.switchmode[i] = SWITCH_MODE; - } - if (sysCfg.version < 0x04000200) { - sysCfg.ex_button_restrict = 0; - } - if (sysCfg.version < 0x04000400) { - CFG_DefaultSet_4_0_4(); - } - if (sysCfg.version < 0x04000500) { - memmove(sysCfg.my_module.gp.io, sysCfg.my_module.gp.io +1, MAX_GPIO_PIN -1); // move myio 1 byte to front - sysCfg.my_module.gp.io[MAX_GPIO_PIN -1] = 0; // Clear ADC0 - } - if (sysCfg.version < 0x04000700) { - for (byte i = 0; i < 5; i++) { - sysCfg.pwmvalue[i] = 0; + if (Settings.version < 0x03091500) { + for (byte i = 0; i < MAX_SWITCHES; i++) { + Settings.switchmode[i] = SWITCH_MODE; } } - if (sysCfg.version < 0x04000804) { - CFG_DefaultSet_4_0_9(); + if (Settings.version < 0x04000400) { + SettingsDefaultSet_4_0_4(); } - if (sysCfg.version < 0x04010100) { - CFG_DefaultSet_4_1_1(); + if (Settings.version < 0x04000500) { + memmove(Settings.my_gp.io, Settings.my_gp.io +1, MAX_GPIO_PIN -1); // move myio 1 byte to front + Settings.my_gp.io[MAX_GPIO_PIN -1] = 0; // Clear ADC0 } - if (sysCfg.version < 0x05000105) { - sysCfg.flag = { 0 }; - sysCfg.flag.savestate = SAVE_STATE; - sysCfg.flag.button_restrict = sysCfg.ex_button_restrict; - sysCfg.flag.value_units = sysCfg.ex_value_units; - sysCfg.flag.mqtt_enabled = sysCfg.ex_mqtt_enabled; -// sysCfg.flag.mqtt_response = 0; - sysCfg.flag.mqtt_power_retain = sysCfg.ex_mqtt_power_retain; - sysCfg.flag.mqtt_button_retain = sysCfg.ex_mqtt_button_retain; - sysCfg.flag.mqtt_switch_retain = sysCfg.ex_mqtt_switch_retain; - sysCfg.flag.emulation = sysCfg.ex_emulation; + if (Settings.version < 0x04000700) { + for (byte i = 0; i < MAX_PWMS; i++) { + Settings.pwm_value[i] = 0; + } + } + if (Settings.version < 0x04000804) { + SettingsDefaultSet_4_0_9(); + } + if (Settings.version < 0x04010100) { + SettingsDefaultSet_4_1_1(); + } + if (Settings.version < 0x05000105) { + Settings.flag = { 0 }; + Settings.flag.save_state = SAVE_STATE; +// Settings.flag.button_restrict = 0; +// Settings.flag.value_units = 0; + Settings.flag.mqtt_enabled = MQTT_USE; +// Settings.flag.mqtt_response = 0; +// Settings.flag.mqtt_power_retain = 0; +// Settings.flag.mqtt_button_retain = 0; + Settings.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN; + Settings.flag.emulation = EMULATION; - CFG_DefaultSet_5_0_2(); + SettingsDefaultSet_5_0_2(); - sysCfg.savedata = SAVE_DATA; + Settings.save_data = SAVE_DATA; } - if (sysCfg.version < 0x05000400) { - sysCfg.hlw_kWhtotal = 0; - rtcMem.hlw_kWhtotal = 0; + if (Settings.version < 0x05000400) { + Settings.hlw_kWhtotal = 0; + RtcSettings.hlw_kWhtotal = 0; } - if (sysCfg.version < 0x05000500) { - strlcpy(sysCfg.mqtt_fulltopic, MQTT_FULLTOPIC, sizeof(sysCfg.mqtt_fulltopic)); + if (Settings.version < 0x05000500) { + strlcpy(Settings.mqtt_fulltopic, MQTT_FULLTOPIC, sizeof(Settings.mqtt_fulltopic)); } - if (sysCfg.version < 0x05000600) { - sysCfg.mqtt_retry = MQTT_RETRY_SECS; + if (Settings.version < 0x05000600) { + Settings.mqtt_retry = MQTT_RETRY_SECS; } - if (sysCfg.version < 0x05010100) { - sysCfg.pCounterType = 0; - sysCfg.pCounterDebounce = 0; + if (Settings.version < 0x05010100) { + Settings.pulse_counter_type = 0; + Settings.pulse_counter_debounce = 0; for (byte i = 0; i < MAX_COUNTERS; i++) { - sysCfg.pCounter[i] = 0; - rtcMem.pCounter[i] = 0; + Settings.pulse_counter[i] = 0; + RtcSettings.pulse_counter[i] = 0; } } - if (sysCfg.version < 0x05010600) { - if (sysCfg.version > 0x04010100) { - memcpy(sysCfg.state_text, sysCfg.ex_state_text, 33); - } - strlcpy(sysCfg.state_text[3], MQTT_CMND_HOLD, sizeof(sysCfg.state_text[3])); + if (Settings.version < 0x05010600) { + SettingsDefaultSet_4_1_1(); } - if (sysCfg.version < 0x05010700) { - sysCfg.param[P_HOLD_TIME] = KEY_HOLD_TIME; // Default 4 seconds hold time + if (Settings.version < 0x05010700) { + Settings.param[P_HOLD_TIME] = KEY_HOLD_TIME; // Default 4 seconds hold time } - if (sysCfg.version < 0x05020000) { - sysCfg.param[P_MAX_POWER_RETRY] = MAX_POWER_RETRY; + if (Settings.version < 0x05020000) { + Settings.param[P_MAX_POWER_RETRY] = MAX_POWER_RETRY; } - if (sysCfg.version < 0x05050000) { + if (Settings.version < 0x05050000) { for (byte i = 0; i < 17; i++) { - sysCfg.sfb_code[i][0] = 0; + Settings.rf_code[i][0] = 0; } - memcpy_P(sysCfg.sfb_code[0], sfb_codeDefault, 9); + memcpy_P(Settings.rf_code[0], kDefaultRfCode, 9); } - if (sysCfg.version < 0x05080000) { + if (Settings.version < 0x05080000) { uint8_t cfg_wsflg = 0; for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if (GPIO_WS2812 == sysCfg.my_module.gp.io[i]) { + if (GPIO_WS2812 == Settings.my_gp.io[i]) { cfg_wsflg = 1; } } - if (!sysCfg.led_pixels && cfg_wsflg) { - sysCfg.led_pixels = sysCfg.ws_pixels; - sysCfg.led_color[0] = sysCfg.ws_red; - sysCfg.led_color[1] = sysCfg.ws_green; - sysCfg.led_color[2] = sysCfg.ws_blue; - sysCfg.led_dimmer[0] = sysCfg.ws_dimmer; - sysCfg.led_table = sysCfg.ws_ledtable; - sysCfg.led_fade = sysCfg.ws_fade; - sysCfg.led_speed = sysCfg.ws_speed; - sysCfg.led_scheme = sysCfg.ws_scheme; - sysCfg.led_width = sysCfg.ws_width; - sysCfg.led_wakeup = sysCfg.ws_wakeup; + if (!Settings.light_pixels && cfg_wsflg) { + Settings.light_pixels = Settings.ws_pixels; + Settings.light_color[0] = Settings.ws_red; + Settings.light_color[1] = Settings.ws_green; + Settings.light_color[2] = Settings.ws_blue; + Settings.light_dimmer = Settings.ws_dimmer; + Settings.light_correction = Settings.ws_ledtable; + Settings.light_fade = Settings.ws_fade; + Settings.light_speed = Settings.ws_speed; + Settings.light_scheme = Settings.ws_scheme; + Settings.light_width = Settings.ex_ws_width; + Settings.light_wakeup = Settings.ws_wakeup; } else { - sysCfg.led_pixels = 1; - sysCfg.led_width = 1; + Settings.light_pixels = WS2812_LEDS; + Settings.light_width = 1; } } + if (Settings.version < 0x0508000A) { + Settings.power = Settings.ex_power; + Settings.altitude = 0; + } + if (Settings.version < 0x0508000B) { + for (byte i = 0; i < MAX_GPIO_PIN; i++) { // Move GPIO_LEDs + if ((Settings.my_gp.io[i] >= 25) && (Settings.my_gp.io[i] <= 32)) { // Was GPIO_LED1 + Settings.my_gp.io[i] += 23; // Move GPIO_LED1 + } + } + for (byte i = 0; i < MAX_PWMS; i++) { // Move pwm_value and reset additional pulse_timerrs + Settings.pwm_value[i] = Settings.pulse_timer[4 +i]; + Settings.pulse_timer[4 +i] = 0; + } + } + if (Settings.version < 0x0508000D) { + Settings.pwm_frequency = PWM_FREQ; + Settings.pwm_range = PWM_RANGE; + } + if (Settings.version < 0x0508000E) { + SettingsDefaultSet_5_8_1(); + } - sysCfg.version = VERSION; - CFG_Save(1); + Settings.version = VERSION; + SettingsSave(1); } } diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h new file mode 100644 index 000000000..603ba86f4 --- /dev/null +++ b/sonoff/sonoff.h @@ -0,0 +1,116 @@ +/* + sonoff.h - Master header file for Sonoff-Tasmota + + Copyright (C) 2017 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 + 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 _SONOFF_H_ +#define _SONOFF_H_ + +/*********************************************************************************************\ + * Power Type +\*********************************************************************************************/ + +typedef unsigned long power_t; // Power (Relay) type +#define POWER_MASK 0xffffffffUL // Power (Relay) full mask + +/*********************************************************************************************\ + * Defines +\*********************************************************************************************/ + +// Changes to the following MAX_ defines will impact settings layout +#define MAX_RELAYS 8 // Max number of relays +#define MAX_LEDS 4 // Max number of leds +#define MAX_KEYS 4 // Max number of keys or buttons +#define MAX_SWITCHES 4 // Max number of switches +#define MAX_PWMS 5 // Max number of PWM channels +#define MAX_COUNTERS 4 // Max number of counter sensors +#define MAX_PULSETIMERS 8 // Max number of supported pulse timers +#define MAX_FRIENDLYNAMES 4 // Max number of Friendly names +#define MAX_DOMOTICZ_IDX 4 // Max number of Domoticz device, key and switch indices + +#define MODULE SONOFF_BASIC // [Module] Select default model + +#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 WIFI_HOSTNAME "%s-%04d" // Expands to - + +#define CONFIG_FILE_SIGN 0xA5 // Configuration file signature +#define CONFIG_FILE_XOR 0x5A // Configuration file xor (0 = No Xor) + +#define HLW_PREF_PULSE 12530 // was 4975us = 201Hz = 1000W +#define HLW_UREF_PULSE 1950 // was 1666us = 600Hz = 220V +#define HLW_IREF_PULSE 3500 // was 1666us = 600Hz = 4.545A + +#define MQTT_RETRY_SECS 10 // Minimum seconds to retry MQTT connection +#define APP_POWER 0 // Default saved power state Off +#define WS2812_MAX_LEDS 512 // Max number of LEDs + +#define PWM_RANGE 1023 // 255..1023 needs to be devisible by 256 +//#define PWM_FREQ 1000 // 100..1000 Hz led refresh +//#define PWM_FREQ 910 // 100..1000 Hz led refresh (iTead value) +#define PWM_FREQ 880 // 100..1000 Hz led refresh (BN-SZ01 value) + +#define MAX_POWER_HOLD 10 // Time in SECONDS to allow max agreed power (Pow) +#define MAX_POWER_WINDOW 30 // Time in SECONDS to disable allow max agreed power (Pow) +#define SAFE_POWER_HOLD 10 // Time in SECONDS to allow max unit safe power (Pow) +#define SAFE_POWER_WINDOW 30 // Time in MINUTES to disable allow max unit safe power (Pow) +#define MAX_POWER_RETRY 5 // Retry count allowing agreed power limit overflow (Pow) + +#define STATES 20 // State loops per second +#define SYSLOG_TIMER 600 // Seconds to restore syslog_level +#define SERIALLOG_TIMER 600 // Seconds to disable SerialLog +#define OTA_ATTEMPTS 10 // Number of times to try fetching the new firmware + +#define INPUT_BUFFER_SIZE 250 // Max number of characters in (serial) command buffer +#define CMDSZ 24 // Max number of characters in command +#define TOPSZ 100 // Max number of characters in topic string +#ifdef USE_MQTT_TLS + #define MAX_LOG_LINES 10 // Max number of lines in weblog +#else + #define MAX_LOG_LINES 20 // Max number of lines in weblog +#endif +#define MAX_BACKLOG 16 // Max number of commands in backlog (chk backlog_index and backlog_pointer code) +#define MIN_BACKLOG_DELAY 2 // Minimal backlog delay in 0.1 seconds + +#define APP_BAUDRATE 115200 // Default serial baudrate +#define MAX_STATUS 11 // Max number of status lines + +/*********************************************************************************************\ + * Enumeration +\*********************************************************************************************/ + +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 LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; +enum WifiConfigOptions {WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, MAX_WIFI_OPTION}; +enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, MAX_SWITCH_OPTION}; +enum LedStateOptions {LED_OFF, LED_POWER, LED_MQTTSUB, LED_POWER_MQTTSUB, LED_MQTTPUB, LED_POWER_MQTTPUB, LED_MQTT, LED_POWER_MQTT, MAX_LED_OPTION}; +enum EmulationOptions {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX}; +enum ButtonStates {PRESSED, NOT_PRESSED}; +enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_MAX_PARAM8}; +enum Ws2812ClockIndex {WS_SECOND, WS_MINUTE, WS_HOUR}; +enum Ws2812Color {WS_RED, WS_GREEN, WS_BLUE}; +enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, LT_NU8, LT_NU9, LT_NU10, LT_WS2812, LT_RGBW, LT_RGBWC}; +enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC}; +enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; + +const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; + +#endif // _SONOFF_H_ \ No newline at end of file diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index d1f74726c..cc20d5af0 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,148 +25,22 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05080000 // 5.8.0 +#define VERSION 0x05090000 // 5.9.0 -enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; -enum week_t {Last, First, Second, Third, Fourth}; -enum dow_t {Sun=1, Mon, Tue, Wed, Thu, Fri, Sat}; -enum month_t {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec}; -enum wifi_t {WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, MAX_WIFI_OPTION}; -enum swtch_t {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, MAX_SWITCH_OPTION}; -enum led_t {LED_OFF, LED_POWER, LED_MQTTSUB, LED_POWER_MQTTSUB, LED_MQTTPUB, LED_POWER_MQTTPUB, LED_MQTT, LED_POWER_MQTT, MAX_LED_OPTION}; -enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX}; - -#include "user_config.h" -#include "user_config_override.h" -#include "i18n.h" -#include "sonoff_template.h" - -/*********************************************************************************************\ - * No user configurable items below -\*********************************************************************************************/ - -#define MODULE SONOFF_BASIC // [Module] Select default model - -#define USE_DHT // Default DHT11 sensor needs no external library -#ifndef USE_DS18x20 -#define USE_DS18B20 // Default DS18B20 sensor needs no external library -#endif -//#define DEBUG_THEO // Add debug code - -#ifdef BE_MINIMAL -#ifdef USE_MQTT_TLS -#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set -#endif -#ifdef USE_DISCOVERY -#undef USE_DISCOVERY // Disable Discovery services for both MQTT and web server -#endif -#ifdef USE_DOMOTICZ -#undef USE_DOMOTICZ // Disable Domoticz -#endif -//#ifdef USE_WEBSERVER -//#undef USE_WEBSERVER // Disable Webserver -//#endif -#ifdef USE_EMULATION -#undef USE_EMULATION // Disable Wemo or Hue emulation -#endif -#ifdef USE_DS18x20 -#undef USE_DS18x20 // Disable DS18x20 sensor -#endif -#ifdef USE_I2C -#undef USE_I2C // Disable all I2C sensors -#endif -#ifdef USE_WS2812 -#undef USE_WS2812 // Disable WS2812 Led string -#endif -#ifdef USE_DS18B20 -#undef USE_DS18B20 // Disable internal DS18B20 sensor -#endif -#ifdef USE_DHT -#undef USE_DHT // Disable internal DHT sensor -#endif -#ifdef USE_IR_REMOTE -#undef USE_IR_REMOTE // Disable IR driver -#endif -#ifdef DEBUG_THEO -#undef DEBUG_THEO // Disable debug code -#endif -#endif // BE_MINIMAL - -#ifndef SWITCH_MODE -#define SWITCH_MODE TOGGLE // TOGGLE, FOLLOW or FOLLOW_INV (the wall switch state) -#endif - -#ifndef MQTT_FINGERPRINT -#define MQTT_FINGERPRINT "A5 02 FF 13 99 9F 8B 39 8E F1 83 4F 11 23 65 0B 32 36 FC 07" -#endif - -#ifndef WS2812_LEDS -#define WS2812_LEDS 30 // [Pixels] Number of LEDs -#endif - -#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 WIFI_HOSTNAME "%s-%04d" // Expands to - -#define CONFIG_FILE_SIGN 0xA5 // Configuration file signature -#define CONFIG_FILE_XOR 0x5A // Configuration file xor (0 = No Xor) - -#define HLW_PREF_PULSE 12530 // was 4975us = 201Hz = 1000W -#define HLW_UREF_PULSE 1950 // was 1666us = 600Hz = 220V -#define HLW_IREF_PULSE 3500 // was 1666us = 600Hz = 4.545A - -#define MQTT_RETRY_SECS 10 // Minimum seconds to retry MQTT connection -#define APP_POWER 0 // Default saved power state Off -#define MAX_COUNTERS 4 // Max number of counter sensors -#define MAX_PULSETIMERS 4 // Max number of supported pulse timers -#define WS2812_MAX_LEDS 512 // Max number of LEDs - -#define PWM_RANGE 1023 // 255..1023 needs to be devisible by 256 -//#define PWM_FREQ 1000 // 100..1000 Hz led refresh -//#define PWM_FREQ 910 // 100..1000 Hz led refresh (iTead value) -#define PWM_FREQ 880 // 100..1000 Hz led refresh (BN-SZ01 value) - -#define MAX_POWER_HOLD 10 // Time in SECONDS to allow max agreed power (Pow) -#define MAX_POWER_WINDOW 30 // Time in SECONDS to disable allow max agreed power (Pow) -#define SAFE_POWER_HOLD 10 // Time in SECONDS to allow max unit safe power (Pow) -#define SAFE_POWER_WINDOW 30 // Time in MINUTES to disable allow max unit safe power (Pow) -#define MAX_POWER_RETRY 5 // Retry count allowing agreed power limit overflow (Pow) - -#define STATES 20 // State loops per second -#define SYSLOG_TIMER 600 // Seconds to restore syslog_level -#define SERIALLOG_TIMER 600 // Seconds to disable SerialLog -#define OTA_ATTEMPTS 10 // Number of times to try fetching the new firmware - -#define INPUT_BUFFER_SIZE 250 // Max number of characters in (serial) command buffer -#define CMDSZ 20 // Max number of characters in command -#define TOPSZ 100 // Max number of characters in topic string -#ifdef USE_MQTT_TLS - #define MAX_LOG_LINES 10 // Max number of lines in weblog -#else - #define MAX_LOG_LINES 20 // Max number of lines in weblog -#endif -#define MAX_BACKLOG 16 // Max number of commands in backlog (chk blogidx and blogptr code) -#define MIN_BACKLOG_DELAY 2 // Minimal backlog delay in 0.1 seconds - -#define APP_BAUDRATE 115200 // Default serial baudrate -#define MAX_STATUS 11 // Max number of status lines - -enum butt_t {PRESSED, NOT_PRESSED}; -enum opt_t {P_HOLD_TIME, P_MAX_POWER_RETRY, P_MAX_PARAM8}; // Index in sysCfg.param - -#include "support.h" // Global support +// Location specific includes +#include "sonoff.h" // Enumaration used in user_config.h +#include "user_config.h" // Fixed user configurable options +#include "user_config_override.h" // Configuration overrides for user_config.h +#include "i18n.h" // Language support configured by user_config.h +#include "sonoff_template.h" // Hardware configuration +#include "sonoff_post.h" // Configuration overrides for all previous includes +// Libraries #include // MQTT -#ifndef MESSZ - #define MESSZ 405 // Max number of characters in JSON message string (4 x DS18x20 sensors) -#endif - // Max message size calculated by PubSubClient is (MQTT_MAX_PACKET_SIZE < 5 + 2 + strlen(topic) + plength) -#if (MQTT_MAX_PACKET_SIZE -TOPSZ -7) < MESSZ // If the max message size is too small, throw an error at compile time - // See pubsubclient.c line 359 +#if (MQTT_MAX_PACKET_SIZE -TOPSZ -7) < MESSZ // If the max message size is too small, throw an error at compile time. See PubSubClient.cpp line 359 #error "MQTT_MAX_PACKET_SIZE is too small in libraries/PubSubClient/src/PubSubClient.h, increase it to at least 512" #endif - #include // RTC, HLW8012, OSWatch #include // MQTT, Ota, WifiManager #include // MQTT, Ota @@ -186,124 +60,141 @@ enum opt_t {P_HOLD_TIME, P_MAX_POWER_RETRY, P_MAX_PARAM8}; // Index in sysCf #ifdef USE_SPI #include // SPI support, TFT #endif // USE_SPI + +// Structs #include "settings.h" -struct TIME_T { - uint8_t Second; - uint8_t Minute; - uint8_t Hour; - uint8_t Wday; // day of week, sunday is day 1 - uint8_t Day; - uint8_t Month; - char MonthName[4]; - uint16_t DayOfYear; - uint16_t Year; - unsigned long Valid; -} rtcTime; +enum TasmotaCommands { + CMND_BACKLOG, CMND_DELAY, CMND_POWER, CMND_STATUS, CMND_POWERONSTATE, CMND_PULSETIME, + CMND_BLINKTIME, CMND_BLINKCOUNT, CMND_SAVEDATA, CMND_SETOPTION, CMND_TEMPERATURE_RESOLUTION, CMND_HUMIDITY_RESOLUTION, + CMND_PRESSURE_RESOLUTION, CMND_POWER_RESOLUTION, CMND_VOLTAGE_RESOLUTION, CMND_ENERGY_RESOLUTION, CMND_MODULE, CMND_MODULES, + CMND_GPIO, CMND_GPIOS, CMND_PWM, CMND_PWMFREQUENCY, CMND_PWMRANGE, CMND_COUNTER, CMND_COUNTERTYPE, + CMND_COUNTERDEBOUNCE, CMND_SLEEP, CMND_UPGRADE, CMND_UPLOAD, CMND_OTAURL, CMND_SERIALLOG, CMND_SYSLOG, + CMND_LOGHOST, CMND_LOGPORT, CMND_IPADDRESS, CMND_NTPSERVER, CMND_AP, CMND_SSID, CMND_PASSWORD, CMND_HOSTNAME, + CMND_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_WEBSERVER, CMND_WEBPASSWORD, CMND_WEBLOG, CMND_EMULATION, + CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE, + CMND_CFGDUMP, CMND_I2CSCAN, CMND_EXCEPTION }; +const char kTasmotaCommands[] PROGMEM = + D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_STATUS "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|" + D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SAVEDATA "|" D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|" + D_CMND_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_MODULE "|" D_CMND_MODULES "|" + D_CMND_GPIO "|" D_CMND_GPIOS "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|" D_CMND_COUNTER "|" D_CMND_COUNTERTYPE "|" + D_CMND_COUNTERDEBOUNCE "|" D_CMND_SLEEP "|" D_CMND_UPGRADE "|" D_CMND_UPLOAD "|" D_CMND_OTAURL "|" D_CMND_SERIALLOG "|" D_CMND_SYSLOG "|" + D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" + D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_EMULATION "|" + D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" + D_CMND_CFGDUMP "|" D_CMND_I2CSCAN +#ifdef DEBUG_THEO + "|" D_CMND_EXCEPTION +#endif + ; -struct TimeChangeRule -{ - uint8_t week; // 1=First, 2=Second, 3=Third, 4=Fourth, or 0=Last week of the month - uint8_t dow; // day of week, 1=Sun, 2=Mon, ... 7=Sat - uint8_t month; // 1=Jan, 2=Feb, ... 12=Dec - uint8_t hour; // 0-23 - int offset; // offset from UTC in minutes -}; +enum MqttCommands { + CMND_MQTTHOST, CMND_MQTTPORT, CMND_MQTTRETRY, CMND_STATETEXT, CMND_MQTTFINGERPRINT, CMND_MQTTCLIENT, + CMND_MQTTUSER, CMND_MQTTPASSWORD, CMND_FULLTOPIC, CMND_PREFIX, CMND_GROUPTOPIC, CMND_TOPIC, + CMND_BUTTONTOPIC, CMND_SWITCHTOPIC, CMND_BUTTONRETAIN, CMND_SWITCHRETAIN, CMND_POWERRETAIN, CMND_SENSORRETAIN }; +const char kMqttCommands[] PROGMEM = + D_CMND_MQTTHOST "|" D_CMND_MQTTPORT "|" D_CMND_MQTTRETRY "|" D_CMND_STATETEXT "|" D_CMND_MQTTFINGERPRINT "|" D_CMND_MQTTCLIENT "|" + D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" D_CMND_FULLTOPIC "|" D_CMND_PREFIX "|" D_CMND_GROUPTOPIC "|" D_CMND_TOPIC "|" + D_CMND_BUTTONTOPIC "|" D_CMND_SWITCHTOPIC "|" D_CMND_BUTTONRETAIN "|" D_CMND_SWITCHRETAIN "|" D_CMND_POWERRETAIN "|" D_CMND_SENSORRETAIN ; -TimeChangeRule myDST = { TIME_DST }; // Daylight Saving Time -TimeChangeRule mySTD = { TIME_STD }; // Standard Time +const char kOptionOff[] PROGMEM = "OFF|" D_OFF "|" D_FALSE "|" D_STOP "|" D_CELSIUS ; +const char kOptionOn[] PROGMEM = "ON|" D_ON "|" D_TRUE "|" D_START "|" D_FAHRENHEIT "|" D_USER ; +const char kOptionToggle[] PROGMEM = "TOGGLE|" D_TOGGLE "|" D_ADMIN ; +const char kOptionBlink[] PROGMEM = "BLINK|" D_BLINK ; +const char kOptionBlinkOff[] PROGMEM = "BLINKOFF|" D_BLINKOFF ; -int Baudrate = APP_BAUDRATE; // Serial interface baud rate -byte SerialInByte; // Received byte -int SerialInByteCounter = 0; // Index in receive buffer -byte Hexcode = 0; // Sonoff dual input flag -uint16_t ButtonCode = 0; // Sonoff dual received code -int16_t savedatacounter; // Counter and flag for config save to Flash -uint8_t mqttcounter = 0; // MQTT connection retry counter -uint8_t fallbacktopic = 0; // Use Topic or FallbackTopic -unsigned long timerxs = 0; // State loop timer -int state = 0; // State per second flag -int mqttflag = 2; // MQTT connection messages flag -int otaflag = 0; // OTA state flag -int otaok = 0; // OTA result -byte otaretry = OTA_ATTEMPTS; // OTA retry counter -int restartflag = 0; // Sonoff restart flag -int wificheckflag = WIFI_RESTART; // Wifi state flag -int uptime = 0; // Current uptime in hours -boolean uptime_flg = true; // Signal latest uptime -int tele_period = 0; // Tele period timer -byte logidx = 0; // Index in Web log buffer -byte logajaxflg = 0; // Reset web console log -byte Maxdevice = 0; // Max number of devices supported -int status_update_timer = 0; // Refresh initial status +// Global variables +int baudrate = APP_BAUDRATE; // Serial interface baud rate +byte serial_in_byte; // Received byte +int serial_in_byte_counter = 0; // Index in receive buffer +byte dual_hex_code = 0; // Sonoff dual input flag +uint16_t dual_button_code = 0; // Sonoff dual received code +int16_t save_data_counter; // Counter and flag for config save to Flash +uint8_t mqtt_retry_counter = 0; // MQTT connection retry counter +uint8_t fallback_topic_flag = 0; // Use Topic or FallbackTopic +unsigned long state_loop_timer = 0; // State loop timer +int state = 0; // State per second flag +int mqtt_connection_flag = 2; // MQTT connection messages flag +int ota_state_flag = 0; // OTA state flag +int ota_result = 0; // OTA result +byte ota_retry_counter = OTA_ATTEMPTS; // OTA retry counter +int restart_flag = 0; // Sonoff restart flag +int wifi_state_flag = WIFI_RESTART; // Wifi state flag +int uptime = 0; // Current uptime in hours +boolean latest_uptime_flag = true; // Signal latest uptime +int tele_period = 0; // Tele period timer +byte web_log_index = 0; // Index in Web log buffer +byte reset_web_log_flag = 0; // Reset web console log +byte devices_present = 0; // Max number of devices supported +int status_update_timer = 0; // Refresh initial status uint16_t pulse_timer[MAX_PULSETIMERS] = { 0 }; // Power off timer -uint16_t blink_timer = 0; // Power cycle timer -uint16_t blink_counter = 0; // Number of blink cycles -uint8_t blink_power; // Blink power state -uint8_t blink_mask = 0; // Blink relay active mask -uint8_t blink_powersave; // Blink start power save state -uint16_t mqtt_cmnd_publish = 0; // ignore flag for publish command -uint8_t latching_power = 0; // Power state at latching start -uint8_t latching_relay_pulse = 0; // Latching relay pulse timer -uint8_t blogidx = 0; // Command backlog index -uint8_t blogptr = 0; // Command backlog pointer -uint8_t blogmutex = 0; // Command backlog pending -uint16_t blogdelay = 0; // Command backlog delay -uint8_t interlockmutex = 0; // Interlock power command pending +uint16_t blink_timer = 0; // Power cycle timer +uint16_t blink_counter = 0; // Number of blink cycles +power_t blink_power; // Blink power state +power_t blink_mask = 0; // Blink relay active mask +power_t blink_powersave; // Blink start power save state +uint16_t mqtt_cmnd_publish = 0; // ignore flag for publish command +power_t latching_power = 0; // Power state at latching start +uint8_t latching_relay_pulse = 0; // Latching relay pulse timer +uint8_t backlog_index = 0; // Command backlog index +uint8_t backlog_pointer = 0; // Command backlog pointer +uint8_t backlog_mutex = 0; // Command backlog pending +uint16_t backlog_delay = 0; // Command backlog delay +uint8_t interlock_mutex = 0; // Interlock power command pending #ifdef USE_MQTT_TLS - WiFiClientSecure espClient; // Wifi Secure Client + WiFiClientSecure EspClient; // Wifi Secure Client #else - WiFiClient espClient; // Wifi Client + WiFiClient EspClient; // Wifi Client #endif -PubSubClient mqttClient(espClient); // MQTT Client -WiFiUDP portUDP; // UDP Syslog and Alexa +PubSubClient MqttClient(EspClient); // MQTT Client +WiFiUDP PortUdp; // UDP Syslog and Alexa -uint8_t power; // Current copy of sysCfg.power -byte syslog_level; // Current copy of sysCfg.syslog_level -uint16_t syslog_timer = 0; // Timer to re-enable syslog_level -byte seriallog_level; // Current copy of sysCfg.seriallog_level -uint16_t seriallog_timer = 0; // Timer to disable Seriallog -uint8_t sleep; // Current copy of sysCfg.sleep -uint8_t stop_flash_rotate = 0; // Allow flash configuration rotation +power_t power = 0; // Current copy of Settings.power +byte syslog_level; // Current copy of Settings.syslog_level +uint16_t syslog_timer = 0; // Timer to re-enable syslog_level +byte seriallog_level; // Current copy of Settings.seriallog_level +uint16_t seriallog_timer = 0; // Timer to disable Seriallog +uint8_t sleep; // Current copy of Settings.sleep +uint8_t stop_flash_rotate = 0; // Allow flash configuration rotation -int blinks = 201; // Number of LED blinks -uint8_t blinkstate = 0; // LED state +int blinks = 201; // Number of LED blinks +uint8_t blinkstate = 0; // LED state -uint8_t lastbutton[4] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; // Last button states -uint8_t holdbutton[4] = { 0 }; // Timer for button hold -uint8_t multiwindow[4] = { 0 }; // Max time between button presses to record press count -uint8_t multipress[4] = { 0 }; // Number of button presses within multiwindow -uint8_t lastwallswitch[4]; // Last wall switch states -uint8_t holdwallswitch[4] = { 0 }; // Timer for wallswitch push button hold -uint8_t blockgpio0 = 4; // Block GPIO0 for 4 seconds after poweron to workaround Wemos D1 RTS circuit +uint8_t blockgpio0 = 4; // Block GPIO0 for 4 seconds after poweron to workaround Wemos D1 RTS circuit +uint8_t lastbutton[MAX_KEYS] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; // Last button states +uint8_t holdbutton[MAX_KEYS] = { 0 }; // Timer for button hold +uint8_t multiwindow[MAX_KEYS] = { 0 }; // Max time between button presses to record press count +uint8_t multipress[MAX_KEYS] = { 0 }; // Number of button presses within multiwindow +uint8_t lastwallswitch[MAX_SWITCHES]; // Last wall switch states +uint8_t holdwallswitch[MAX_SWITCHES] = { 0 }; // Timer for wallswitch push button hold -mytmplt my_module; // Active copy of GPIOs -uint8_t pin[GPIO_MAX]; // Possible pin configurations -uint8_t rel_inverted[4] = { 0 }; // Relay inverted flag (1 = (0 = On, 1 = Off)) -uint8_t led_inverted[4] = { 0 }; // LED inverted flag (1 = (0 = On, 1 = Off)) -uint8_t dht_flg = 0; // DHT configured -uint8_t hlw_flg = 0; // Power monitor configured -uint8_t i2c_flg = 0; // I2C configured -uint8_t spi_flg = 0; // SPI configured -uint8_t pwm_flg = 0; // PWM configured -uint8_t sfl_flg = 0; // Sonoff Led flag (0 = No led, 1 = BN-SZ01, 2 = Sonoff Led, 5 = Sonoff B1) -uint8_t pwm_idxoffset = 0; // Allowed PWM command offset (change for Sonoff Led) +mytmplt my_module; // Active copy of Module name and GPIOs +uint8_t pin[GPIO_MAX]; // Possible pin configurations +power_t rel_inverted = 0; // Relay inverted flag (1 = (0 = On, 1 = Off)) +uint8_t led_inverted = 0; // LED inverted flag (1 = (0 = On, 1 = Off)) +uint8_t pwm_inverted = 0; // PWM inverted flag (1 = inverted) +uint8_t dht_flg = 0; // DHT configured +uint8_t hlw_flg = 0; // Power monitor configured +uint8_t i2c_flg = 0; // I2C configured +uint8_t spi_flg = 0; // SPI configured +uint8_t light_type = 0; // Light types -boolean mDNSbegun = false; +boolean mdns_begun = false; -char Version[16]; // Version string from VERSION define -char Hostname[33]; // Composed Wifi hostname -char MQTTClient[33]; // Composed MQTT Clientname -char serialInBuf[INPUT_BUFFER_SIZE + 2]; // Receive buffer -char mqtt_data[MESSZ]; // MQTT publish buffer -char log_data[TOPSZ + MESSZ]; // Logging -String Log[MAX_LOG_LINES]; // Web log buffer -String Backlog[MAX_BACKLOG]; // Command backlog +char version[16]; // Version string from VERSION define +char my_hostname[33]; // Composed Wifi hostname +char mqtt_client[33]; // Composed MQTT Clientname +char serial_in_buffer[INPUT_BUFFER_SIZE + 2]; // Receive buffer +char mqtt_data[MESSZ]; // MQTT publish buffer +char log_data[TOPSZ + MESSZ]; // Logging +String web_log[MAX_LOG_LINES]; // Web log buffer +String backlog[MAX_BACKLOG]; // Command backlog /********************************************************************************************/ -void getClient(char* output, const char* input, byte size) +void GetMqttClient(char* output, const char* input, byte size) { char *token; uint8_t digits = 0; @@ -329,27 +220,27 @@ void getClient(char* output, const char* input, byte size) } } -void getTopic_P(char *stopic, byte prefix, char *topic, const char* subtopic) +void GetTopic_P(char *stopic, byte prefix, char *topic, const char* subtopic) { char romram[CMDSZ]; String fulltopic; snprintf_P(romram, sizeof(romram), subtopic); - if (fallbacktopic) { - fulltopic = FPSTR(PREFIXES[prefix]); + if (fallback_topic_flag) { + fulltopic = FPSTR(kPrefixes[prefix]); fulltopic += F("/"); - fulltopic += MQTTClient; + fulltopic += mqtt_client; } else { - fulltopic = sysCfg.mqtt_fulltopic; + fulltopic = Settings.mqtt_fulltopic; if ((0 == prefix) && (-1 == fulltopic.indexOf(F(MQTT_TOKEN_PREFIX)))) { fulltopic += F("/" MQTT_TOKEN_PREFIX); // Need prefix for commands to handle mqtt topic loops } for (byte i = 0; i < 3; i++) { - if ('\0' == sysCfg.mqtt_prefix[i][0]) { - snprintf_P(sysCfg.mqtt_prefix[i], sizeof(sysCfg.mqtt_prefix[i]), PREFIXES[i]); + if ('\0' == Settings.mqtt_prefix[i][0]) { + snprintf_P(Settings.mqtt_prefix[i], sizeof(Settings.mqtt_prefix[i]), kPrefixes[i]); } } - fulltopic.replace(F(MQTT_TOKEN_PREFIX), sysCfg.mqtt_prefix[prefix]); + fulltopic.replace(F(MQTT_TOKEN_PREFIX), Settings.mqtt_prefix[prefix]); fulltopic.replace(F(MQTT_TOKEN_TOPIC), topic); } fulltopic.replace(F("#"), ""); @@ -360,17 +251,17 @@ void getTopic_P(char *stopic, byte prefix, char *topic, const char* subtopic) snprintf_P(stopic, TOPSZ, PSTR("%s%s"), fulltopic.c_str(), romram); } -char* getStateText(byte state) +char* GetStateText(byte state) { if (state > 3) { state = 1; } - return sysCfg.state_text[state]; + return Settings.state_text[state]; } /********************************************************************************************/ -void setLatchingRelay(uint8_t power, uint8_t state) +void SetLatchingRelay(power_t power, uint8_t state) { power &= 1; if (2 == state) { // Reset relay @@ -380,25 +271,25 @@ void setLatchingRelay(uint8_t power, uint8_t state) } else if (state && !latching_relay_pulse) { // Set port power to On latching_power = power; - latching_relay_pulse = 2; // max 200mS (initiated by stateloop()) + latching_relay_pulse = 2; // max 200mS (initiated by stateloop()) } if (pin[GPIO_REL1 +latching_power] < 99) { - digitalWrite(pin[GPIO_REL1 +latching_power], rel_inverted[latching_power] ? !state : state); + digitalWrite(pin[GPIO_REL1 +latching_power], bitRead(rel_inverted, latching_power) ? !state : state); } } -void setRelay(uint8_t rpower) +void SetDevicePower(power_t rpower) { uint8_t state; - if (4 == sysCfg.poweronstate) { // All on and stay on - power = (1 << Maxdevice) -1; + if (4 == Settings.poweronstate) { // All on and stay on + power = (1 << devices_present) -1; rpower = power; } - if (sysCfg.flag.interlock) { // Allow only one or no relay set - uint8_t mask = 0x01; + if (Settings.flag.interlock) { // Allow only one or no relay set + power_t mask = 1; uint8_t count = 0; - for (byte i = 0; i < Maxdevice; i++) { + for (byte i = 0; i < devices_present; i++) { if (rpower & mask) { count++; } @@ -409,48 +300,56 @@ void setRelay(uint8_t rpower) rpower = 0; } } - if ((SONOFF_DUAL == sysCfg.module) || (CH4 == sysCfg.module)) { + if (light_type) { + LightSetPower(bitRead(rpower, devices_present -1)); + } + if ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) { Serial.write(0xA0); Serial.write(0x04); - Serial.write(rpower); + Serial.write(rpower &0xFF); Serial.write(0xA1); Serial.write('\n'); Serial.flush(); } - else if (sfl_flg) { - sl_setPower(rpower); - } - else if (EXS_RELAY == sysCfg.module) { - setLatchingRelay(rpower, 1); + else if (EXS_RELAY == Settings.module) { + SetLatchingRelay(rpower, 1); } else { - for (byte i = 0; i < Maxdevice; i++) { + for (byte i = 0; i < devices_present; i++) { state = rpower &1; - if (pin[GPIO_REL1 +i] < 99) { - digitalWrite(pin[GPIO_REL1 +i], rel_inverted[i] ? !state : state); + if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) { + digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? !state : state); } rpower >>= 1; } } - hlw_setPowerSteadyCounter(2); + HlwSetPowerSteadyCounter(2); } -void setLed(uint8_t state) +void SetLedPower(uint8_t state) { if (state) { state = 1; } - digitalWrite(pin[GPIO_LED1], (led_inverted[0]) ? !state : state); + digitalWrite(pin[GPIO_LED1], (bitRead(led_inverted, 0)) ? !state : state); } /********************************************************************************************/ -void mqtt_publish_sec(const char* topic, boolean retained) +void MqttSubscribe(char *topic) { - if (sysCfg.flag.mqtt_enabled) { - if (mqttClient.publish(topic, mqtt_data, retained)) { + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_SUBSCRIBE_TO " %s"), topic); + AddLog(LOG_LEVEL_DEBUG); + MqttClient.subscribe(topic); + MqttClient.loop(); // Solve LmacRxBlk:1 messages +} + +void MqttPublishDirect(const char* topic, boolean retained) +{ + if (Settings.flag.mqtt_enabled) { + if (MqttClient.publish(topic, mqtt_data, retained)) { snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT "%s = %s%s"), topic, mqtt_data, (retained) ? " (" D_RETAINED ")" : ""); -// mqttClient.loop(); // Do not use here! Will block previous publishes +// MqttClient.loop(); // Do not use here! Will block previous publishes } else { snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_RESULT "%s = %s"), topic, mqtt_data); } @@ -458,31 +357,31 @@ void mqtt_publish_sec(const char* topic, boolean retained) snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_RESULT "%s = %s"), strrchr(topic,'/')+1, mqtt_data); } - addLog(LOG_LEVEL_INFO); - if (sysCfg.ledstate &0x04) { + AddLog(LOG_LEVEL_INFO); + if (Settings.ledstate &0x04) { blinks++; } } -void mqtt_publish(const char* topic, boolean retained) +void MqttPublish(const char* topic, boolean retained) { char *me; - if (!strcmp(sysCfg.mqtt_prefix[0],sysCfg.mqtt_prefix[1])) { - me = strstr(topic,sysCfg.mqtt_prefix[0]); + if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1])) { + me = strstr(topic,Settings.mqtt_prefix[0]); if (me == topic) { mqtt_cmnd_publish += 8; } } - mqtt_publish_sec(topic, retained); + MqttPublishDirect(topic, retained); } -void mqtt_publish(const char* topic) +void MqttPublish(const char* topic) { - mqtt_publish(topic, false); + MqttPublish(topic, false); } -void mqtt_publish_topic_P(uint8_t prefix, const char* subtopic, boolean retained) +void MqttPublishPrefixTopic_P(uint8_t prefix, const char* subtopic, boolean retained) { /* prefix 0 = cmnd using subtopic * prefix 1 = stat using subtopic @@ -494,357 +393,371 @@ void mqtt_publish_topic_P(uint8_t prefix, const char* subtopic, boolean retained char romram[16]; char stopic[TOPSZ]; - snprintf_P(romram, sizeof(romram), ((prefix > 3) && !sysCfg.flag.mqtt_response) ? S_RSLT_RESULT : subtopic); + snprintf_P(romram, sizeof(romram), ((prefix > 3) && !Settings.flag.mqtt_response) ? S_RSLT_RESULT : subtopic); for (byte i = 0; i < strlen(romram); i++) { romram[i] = toupper(romram[i]); } prefix &= 3; - getTopic_P(stopic, prefix, sysCfg.mqtt_topic, romram); - mqtt_publish(stopic, retained); + GetTopic_P(stopic, prefix, Settings.mqtt_topic, romram); + MqttPublish(stopic, retained); } -void mqtt_publish_topic_P(uint8_t prefix, const char* subtopic) +void MqttPublishPrefixTopic_P(uint8_t prefix, const char* subtopic) { - mqtt_publish_topic_P(prefix, subtopic, false); + MqttPublishPrefixTopic_P(prefix, subtopic, false); } -void mqtt_publishPowerState(byte device) +void MqttPublishPowerState(byte device) { char stopic[TOPSZ]; char scommand[16]; - if ((device < 1) || (device > Maxdevice)) { + if ((device < 1) || (device > devices_present)) { device = 1; } - getPowerDevice(scommand, device, sizeof(scommand)); - getTopic_P(stopic, 1, sysCfg.mqtt_topic, (sysCfg.flag.mqtt_response) ? scommand : S_RSLT_RESULT); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"), scommand, getStateText(bitRead(power, device -1))); - mqtt_publish(stopic); + GetPowerDevice(scommand, device, sizeof(scommand)); + GetTopic_P(stopic, 1, Settings.mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"), scommand, GetStateText(bitRead(power, device -1))); + MqttPublish(stopic); - getTopic_P(stopic, 1, sysCfg.mqtt_topic, scommand); - snprintf_P(mqtt_data, sizeof(mqtt_data), getStateText(bitRead(power, device -1))); - mqtt_publish(stopic, sysCfg.flag.mqtt_power_retain); + GetTopic_P(stopic, 1, Settings.mqtt_topic, scommand); + snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(bitRead(power, device -1))); + MqttPublish(stopic, Settings.flag.mqtt_power_retain); } -void mqtt_publishPowerBlinkState(byte device) +void MqttPublishPowerBlinkState(byte device) { char scommand[16]; - if ((device < 1) || (device > Maxdevice)) { + if ((device < 1) || (device > devices_present)) { device = 1; } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_BLINK " %s\"}"), - getPowerDevice(scommand, device, sizeof(scommand)), getStateText(bitRead(blink_mask, device -1))); + GetPowerDevice(scommand, device, sizeof(scommand)), GetStateText(bitRead(blink_mask, device -1))); - mqtt_publish_topic_P(5, S_RSLT_POWER); + MqttPublishPrefixTopic_P(5, S_RSLT_POWER); } -void mqtt_connected() +void MqttConnected() { char stopic[TOPSZ]; - if (sysCfg.flag.mqtt_enabled) { + if (Settings.flag.mqtt_enabled) { // Satisfy iobroker (#299) mqtt_data[0] = '\0'; - mqtt_publish_topic_P(0, S_RSLT_POWER); + MqttPublishPrefixTopic_P(0, S_RSLT_POWER); - getTopic_P(stopic, 0, sysCfg.mqtt_topic, PSTR("#")); - mqttClient.subscribe(stopic); - mqttClient.loop(); // Solve LmacRxBlk:1 messages - if (strstr(sysCfg.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != NULL) { - getTopic_P(stopic, 0, sysCfg.mqtt_grptopic, PSTR("#")); - mqttClient.subscribe(stopic); - mqttClient.loop(); // Solve LmacRxBlk:1 messages - fallbacktopic = 1; - getTopic_P(stopic, 0, MQTTClient, PSTR("#")); - fallbacktopic = 0; - mqttClient.subscribe(stopic); - mqttClient.loop(); // Solve LmacRxBlk:1 messages + GetTopic_P(stopic, 0, Settings.mqtt_topic, PSTR("#")); + MqttSubscribe(stopic); + if (strstr(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != NULL) { + GetTopic_P(stopic, 0, Settings.mqtt_grptopic, PSTR("#")); + MqttSubscribe(stopic); + fallback_topic_flag = 1; + GetTopic_P(stopic, 0, mqtt_client, PSTR("#")); + fallback_topic_flag = 0; + MqttSubscribe(stopic); } #ifdef USE_DOMOTICZ - domoticz_mqttSubscribe(); + DomoticzMqttSubscribe(); #endif // USE_DOMOTICZ } - if (mqttflag) { + if (mqtt_connection_flag) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MODULE "\":\"%s\", \"" D_VERSION "\":\"%s\", \"" D_FALLBACKTOPIC "\":\"%s\", \"" D_CMND_GROUPTOPIC "\":\"%s\"}"), - my_module.name, Version, MQTTClient, sysCfg.mqtt_grptopic); - mqtt_publish_topic_P(2, PSTR(D_RSLT_INFO "1")); + my_module.name, version, mqtt_client, Settings.mqtt_grptopic); + MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_INFO "1")); #ifdef USE_WEBSERVER - if (sysCfg.webserver) { + if (Settings.webserver) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_WEBSERVER_MODE "\":\"%s\", \"" D_CMND_HOSTNAME "\":\"%s\", \"" D_CMND_IPADDRESS "\":\"%s\"}"), - (2 == sysCfg.webserver) ? D_ADMIN : D_USER, Hostname, WiFi.localIP().toString().c_str()); - mqtt_publish_topic_P(2, PSTR(D_RSLT_INFO "2")); + (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str()); + MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_INFO "2")); } #endif // USE_WEBSERVER snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_RESTARTREASON "\":\"%s\"}"), - (getResetReason() == "Exception") ? ESP.getResetInfo().c_str() : getResetReason().c_str()); - mqtt_publish_topic_P(2, PSTR(D_RSLT_INFO "3")); - if (sysCfg.tele_period) { - tele_period = sysCfg.tele_period -9; + (GetResetReason() == "Exception") ? ESP.getResetInfo().c_str() : GetResetReason().c_str()); + MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_INFO "3")); + if (Settings.tele_period) { + tele_period = Settings.tele_period -9; } status_update_timer = 2; #ifdef USE_DOMOTICZ - domoticz_setUpdateTimer(2); + DomoticzSetUpdateTimer(2); #endif // USE_DOMOTICZ } - mqttflag = 0; + mqtt_connection_flag = 0; } -void mqtt_reconnect() +void MqttReconnect() { char stopic[TOPSZ]; - mqttcounter = sysCfg.mqtt_retry; + mqtt_retry_counter = Settings.mqtt_retry; - if (!sysCfg.flag.mqtt_enabled) { - mqtt_connected(); + if (!Settings.flag.mqtt_enabled) { + MqttConnected(); return; } #ifdef USE_EMULATION - UDP_Disconnect(); + UdpDisconnect(); #endif // USE_EMULATION - if (mqttflag > 1) { + if (mqtt_connection_flag > 1) { #ifdef USE_MQTT_TLS - addLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_FINGERPRINT)); - if (!espClient.connect(sysCfg.mqtt_host, sysCfg.mqtt_port)) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_FINGERPRINT)); + if (!EspClient.connect(Settings.mqtt_host, Settings.mqtt_port)) { snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_TLS_CONNECT_FAILED_TO " %s:%d. " D_RETRY_IN " %d " D_UNIT_SECOND), - sysCfg.mqtt_host, sysCfg.mqtt_port, mqttcounter); - addLog(LOG_LEVEL_DEBUG); + Settings.mqtt_host, Settings.mqtt_port, mqtt_retry_counter); + AddLog(LOG_LEVEL_DEBUG); return; } - if (espClient.verify(sysCfg.mqtt_fingerprint, sysCfg.mqtt_host)) { - addLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED)); + if (EspClient.verify(Settings.mqtt_fingerprint, Settings.mqtt_host)) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED)); } else { - addLog_P(LOG_LEVEL_DEBUG, S_LOG_MQTT, PSTR(D_INSECURE)); + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_MQTT, PSTR(D_INSECURE)); } + EspClient.stop(); + yield(); #endif // USE_MQTT_TLS - mqttClient.setCallback(mqttDataCb); - mqttflag = 1; - mqttcounter = 1; + MqttClient.setCallback(MqttDataCallback); + mqtt_connection_flag = 1; + mqtt_retry_counter = 1; return; } - addLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); + AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); #ifndef USE_MQTT_TLS #ifdef USE_DISCOVERY #ifdef MQTT_HOST_DISCOVERY - mdns_discoverMQTTServer(); +// if (!strlen(MQTT_HOST)) { + if (!strlen(Settings.mqtt_host)) { + MdnsDiscoverMqttServer(); + } #endif // MQTT_HOST_DISCOVERY #endif // USE_DISCOVERY #endif // USE_MQTT_TLS - mqttClient.setServer(sysCfg.mqtt_host, sysCfg.mqtt_port); + MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); - getTopic_P(stopic, 2, sysCfg.mqtt_topic, S_LWT); + GetTopic_P(stopic, 2, Settings.mqtt_topic, S_LWT); snprintf_P(mqtt_data, sizeof(mqtt_data), S_OFFLINE); - if (mqttClient.connect(MQTTClient, sysCfg.mqtt_user, sysCfg.mqtt_pwd, stopic, 1, true, mqtt_data)) { - addLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_CONNECTED)); - mqttcounter = 0; + + char *mqtt_user = NULL; + char *mqtt_pwd = NULL; + if (strlen(Settings.mqtt_user) > 0) { + mqtt_user = Settings.mqtt_user; + } + if (strlen(Settings.mqtt_pwd) > 0) { + mqtt_pwd = Settings.mqtt_pwd; + } + if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, true, mqtt_data)) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_CONNECTED)); + mqtt_retry_counter = 0; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_ONLINE)); - mqtt_publish(stopic, true); - mqtt_connected(); + MqttPublish(stopic, true); + MqttConnected(); } else { snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), - sysCfg.mqtt_host, sysCfg.mqtt_port, mqttClient.state(), mqttcounter); //status codes are documented here http://pubsubclient.knolleary.net/api.html#state - addLog(LOG_LEVEL_INFO); + Settings.mqtt_host, Settings.mqtt_port, MqttClient.state(), mqtt_retry_counter); //status codes are documented here http://pubsubclient.knolleary.net/api.html#state + AddLog(LOG_LEVEL_INFO); } } /********************************************************************************************/ -boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload, uint16_t payload16) +boolean MqttCommand(boolean grpflg, char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload, uint16_t payload16) { + char command [CMDSZ]; boolean serviced = true; char stemp1[TOPSZ]; char stemp2[10]; char scommand[CMDSZ]; uint16_t i; - if (!strcasecmp_P(type, PSTR(D_CMND_MQTTHOST))) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_host))) { - strlcpy(sysCfg.mqtt_host, (1 == payload) ? MQTT_HOST : dataBuf, sizeof(sysCfg.mqtt_host)); - restartflag = 2; + int command_code = GetCommandCode(command, sizeof(command), type, kMqttCommands); + if (CMND_MQTTHOST == command_code) { + if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_host))) { + strlcpy(Settings.mqtt_host, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? MQTT_HOST : dataBuf, sizeof(Settings.mqtt_host)); + restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MQTTHOST "\":\"%s\"}"), sysCfg.mqtt_host); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_host); } - else if (!strcasecmp_P(type, PSTR(D_CMND_MQTTPORT))) { + else if (CMND_MQTTPORT == command_code) { if (payload16 > 0) { - sysCfg.mqtt_port = (1 == payload16) ? MQTT_PORT : payload16; - restartflag = 2; + Settings.mqtt_port = (1 == payload16) ? MQTT_PORT : payload16; + restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MQTTPORT "\":%d}"), sysCfg.mqtt_port); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.mqtt_port); } - else if (!strcasecmp_P(type, PSTR(D_CMND_MQTTRETRY))) { + else if (CMND_MQTTRETRY == command_code) { if ((payload >= MQTT_RETRY_SECS) && (payload < 32001)) { - sysCfg.mqtt_retry = payload; - mqttcounter = sysCfg.mqtt_retry; + Settings.mqtt_retry = payload; + mqtt_retry_counter = Settings.mqtt_retry; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MQTTRETRY "\":%d}"), sysCfg.mqtt_retry); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.mqtt_retry); } - else if (!strcasecmp_P(type, PSTR(D_CMND_STATETEXT)) && (index > 0) && (index <= 4)) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.state_text[0]))) { + else if ((CMND_STATETEXT == command_code) && (index > 0) && (index <= 4)) { + if ((data_len > 0) && (data_len < sizeof(Settings.state_text[0]))) { for(i = 0; i <= data_len; i++) { if (dataBuf[i] == ' ') { dataBuf[i] = '_'; } } - strlcpy(sysCfg.state_text[index -1], dataBuf, sizeof(sysCfg.state_text[0])); + strlcpy(Settings.state_text[index -1], dataBuf, sizeof(Settings.state_text[0])); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATETEXT "%d\":\"%s\"}"), index, getStateText(index -1)); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, GetStateText(index -1)); } #ifdef USE_MQTT_TLS - else if (!strcasecmp_P(type, PSTR(D_CMND_MQTTFINGERPRINT))) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_fingerprint))) { - strlcpy(sysCfg.mqtt_fingerprint, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? MQTT_FINGERPRINT : dataBuf, sizeof(sysCfg.mqtt_fingerprint)); - restartflag = 2; + else if (CMND_MQTTFINGERPRINT == command_code) { + if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_fingerprint))) { + strlcpy(Settings.mqtt_fingerprint, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? MQTT_FINGERPRINT : dataBuf, sizeof(Settings.mqtt_fingerprint)); + restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MQTTFINGERPRINT "\":\"%s\"}"), sysCfg.mqtt_fingerprint); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_fingerprint); } #endif - else if (!grpflg && !strcasecmp_P(type, PSTR(D_CMND_MQTTCLIENT))) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_client))) { - strlcpy(sysCfg.mqtt_client, (1 == payload) ? MQTT_CLIENT_ID : dataBuf, sizeof(sysCfg.mqtt_client)); - restartflag = 2; + else if ((CMND_MQTTCLIENT == command_code) && !grpflg) { + if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_client))) { + strlcpy(Settings.mqtt_client, (1 == payload) ? MQTT_CLIENT_ID : dataBuf, sizeof(Settings.mqtt_client)); + restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MQTTCLIENT "\":\"%s\"}"), sysCfg.mqtt_client); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_client); } - else if (!strcasecmp_P(type, PSTR(D_CMND_MQTTUSER))) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_user))) { - strlcpy(sysCfg.mqtt_user, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? MQTT_USER : dataBuf, sizeof(sysCfg.mqtt_user)); - restartflag = 2; + else if (CMND_MQTTUSER == command_code) { + if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_user))) { + strlcpy(Settings.mqtt_user, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? MQTT_USER : dataBuf, sizeof(Settings.mqtt_user)); + restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MQTTUSER "\":\"%s\"}"), sysCfg.mqtt_user); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_user); } - else if (!strcasecmp_P(type, PSTR(D_CMND_MQTTPASSWORD))) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_pwd))) { - strlcpy(sysCfg.mqtt_pwd, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? MQTT_PASS : dataBuf, sizeof(sysCfg.mqtt_pwd)); - restartflag = 2; + else if (CMND_MQTTPASSWORD == command_code) { + if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_pwd))) { + strlcpy(Settings.mqtt_pwd, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? MQTT_PASS : dataBuf, sizeof(Settings.mqtt_pwd)); + restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MQTTPASSWORD "\":\"%s\"}"), sysCfg.mqtt_pwd); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_pwd); } - else if (!strcasecmp_P(type, PSTR(D_CMND_FULLTOPIC))) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_fulltopic))) { - mqttfy(1, dataBuf); - if (!strcmp(dataBuf, MQTTClient)) { + else if (CMND_FULLTOPIC == command_code) { + if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_fulltopic))) { + MakeValidMqtt(1, dataBuf); + if (!strcmp(dataBuf, mqtt_client)) { payload = 1; } strlcpy(stemp1, (1 == payload) ? MQTT_FULLTOPIC : dataBuf, sizeof(stemp1)); - if (strcmp(stemp1, sysCfg.mqtt_fulltopic)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), (sysCfg.flag.mqtt_offline) ? S_OFFLINE : ""); - mqtt_publish_topic_P(2, PSTR(D_LWT), true); // Offline or remove previous retained topic - strlcpy(sysCfg.mqtt_fulltopic, stemp1, sizeof(sysCfg.mqtt_fulltopic)); - restartflag = 2; + if (strcmp(stemp1, Settings.mqtt_fulltopic)) { + snprintf_P(mqtt_data, sizeof(mqtt_data), (Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + MqttPublishPrefixTopic_P(2, PSTR(D_LWT), true); // Offline or remove previous retained topic + strlcpy(Settings.mqtt_fulltopic, stemp1, sizeof(Settings.mqtt_fulltopic)); + restart_flag = 2; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_FULLTOPIC "\":\"%s\"}"), sysCfg.mqtt_fulltopic); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_fulltopic); } - else if (!strcasecmp_P(type, PSTR(D_CMND_PREFIX)) && (index > 0) && (index <= 3)) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_prefix[0]))) { - mqttfy(0, dataBuf); - strlcpy(sysCfg.mqtt_prefix[index -1], (1 == payload) ? (1==index)?SUB_PREFIX:(2==index)?PUB_PREFIX:PUB_PREFIX2 : dataBuf, sizeof(sysCfg.mqtt_prefix[0])); -// if (sysCfg.mqtt_prefix[index -1][strlen(sysCfg.mqtt_prefix[index -1])] == '/') sysCfg.mqtt_prefix[index -1][strlen(sysCfg.mqtt_prefix[index -1])] = 0; - restartflag = 2; + else if ((CMND_PREFIX == command_code) && (index > 0) && (index <= 3)) { + if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_prefix[0]))) { + MakeValidMqtt(0, dataBuf); + strlcpy(Settings.mqtt_prefix[index -1], (1 == payload) ? (1==index)?SUB_PREFIX:(2==index)?PUB_PREFIX:PUB_PREFIX2 : dataBuf, sizeof(Settings.mqtt_prefix[0])); +// if (Settings.mqtt_prefix[index -1][strlen(Settings.mqtt_prefix[index -1])] == '/') Settings.mqtt_prefix[index -1][strlen(Settings.mqtt_prefix[index -1])] = 0; + restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_PREFIX "%d\":\"%s\"}"), index, sysCfg.mqtt_prefix[index -1]); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mqtt_prefix[index -1]); } - else if (!strcasecmp_P(type, PSTR(D_CMND_GROUPTOPIC))) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_grptopic))) { - mqttfy(0, dataBuf); - if (!strcmp(dataBuf, MQTTClient)) { + else if (CMND_GROUPTOPIC == command_code) { + if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_grptopic))) { + MakeValidMqtt(0, dataBuf); + if (!strcmp(dataBuf, mqtt_client)) { payload = 1; } - strlcpy(sysCfg.mqtt_grptopic, (1 == payload) ? MQTT_GRPTOPIC : dataBuf, sizeof(sysCfg.mqtt_grptopic)); - restartflag = 2; + strlcpy(Settings.mqtt_grptopic, (1 == payload) ? MQTT_GRPTOPIC : dataBuf, sizeof(Settings.mqtt_grptopic)); + restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), sysCfg.mqtt_grptopic); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_grptopic); } - else if (!grpflg && !strcasecmp_P(type, PSTR(D_CMND_TOPIC))) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_topic))) { - mqttfy(0, dataBuf); - if (!strcmp(dataBuf, MQTTClient)) { + else if ((CMND_TOPIC == command_code) && !grpflg) { + if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_topic))) { + MakeValidMqtt(0, dataBuf); + if (!strcmp(dataBuf, mqtt_client)) { payload = 1; } strlcpy(stemp1, (1 == payload) ? MQTT_TOPIC : dataBuf, sizeof(stemp1)); - if (strcmp(stemp1, sysCfg.mqtt_topic)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), (sysCfg.flag.mqtt_offline) ? S_OFFLINE : ""); - mqtt_publish_topic_P(2, PSTR(D_LWT), true); // Offline or remove previous retained topic - strlcpy(sysCfg.mqtt_topic, stemp1, sizeof(sysCfg.mqtt_topic)); - restartflag = 2; + if (strcmp(stemp1, Settings.mqtt_topic)) { + snprintf_P(mqtt_data, sizeof(mqtt_data), (Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + MqttPublishPrefixTopic_P(2, PSTR(D_LWT), true); // Offline or remove previous retained topic + strlcpy(Settings.mqtt_topic, stemp1, sizeof(Settings.mqtt_topic)); + restart_flag = 2; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_TOPIC "\":\"%s\"}"), sysCfg.mqtt_topic); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_topic); } - else if (!grpflg && !strcasecmp_P(type, PSTR(D_CMND_BUTTONTOPIC))) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.button_topic))) { - mqttfy(0, dataBuf); - if (!strcmp(dataBuf, MQTTClient)) { + else if ((CMND_BUTTONTOPIC == command_code) && !grpflg) { + if ((data_len > 0) && (data_len < sizeof(Settings.button_topic))) { + MakeValidMqtt(0, dataBuf); + if (!strcmp(dataBuf, mqtt_client)) { payload = 1; } - strlcpy(sysCfg.button_topic, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? sysCfg.mqtt_topic : dataBuf, sizeof(sysCfg.button_topic)); + strlcpy(Settings.button_topic, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? Settings.mqtt_topic : dataBuf, sizeof(Settings.button_topic)); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_BUTTONTOPIC "\":\"%s\"}"), sysCfg.button_topic); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.button_topic); } - else if (!strcasecmp_P(type, PSTR(D_CMND_SWITCHTOPIC))) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.switch_topic))) { - mqttfy(0, dataBuf); - if (!strcmp(dataBuf, MQTTClient)) { + else if (CMND_SWITCHTOPIC == command_code) { + if ((data_len > 0) && (data_len < sizeof(Settings.switch_topic))) { + MakeValidMqtt(0, dataBuf); + if (!strcmp(dataBuf, mqtt_client)) { payload = 1; } - strlcpy(sysCfg.switch_topic, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? sysCfg.mqtt_topic : dataBuf, sizeof(sysCfg.switch_topic)); + strlcpy(Settings.switch_topic, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? Settings.mqtt_topic : dataBuf, sizeof(Settings.switch_topic)); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_SWITCHTOPIC "\":\"%s\"}"), sysCfg.switch_topic); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.switch_topic); } - else if (!strcasecmp_P(type, PSTR(D_CMND_BUTTONRETAIN))) { + else if (CMND_BUTTONRETAIN == command_code) { if ((payload >= 0) && (payload <= 1)) { - strlcpy(sysCfg.button_topic, sysCfg.mqtt_topic, sizeof(sysCfg.button_topic)); + strlcpy(Settings.button_topic, Settings.mqtt_topic, sizeof(Settings.button_topic)); if (!payload) { - for(i = 1; i <= Maxdevice; i++) { + for(i = 1; i <= MAX_KEYS; i++) { send_button_power(0, i, 9); // Clear MQTT retain in broker } } - sysCfg.flag.mqtt_button_retain = payload; + Settings.flag.mqtt_button_retain = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_BUTTONRETAIN "\":\"%s\"}"), getStateText(sysCfg.flag.mqtt_button_retain)); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_button_retain)); } - else if (!strcasecmp_P(type, PSTR(D_CMND_SWITCHRETAIN))) { + else if (CMND_SWITCHRETAIN == command_code) { if ((payload >= 0) && (payload <= 1)) { - strlcpy(sysCfg.button_topic, sysCfg.mqtt_topic, sizeof(sysCfg.button_topic)); + strlcpy(Settings.button_topic, Settings.mqtt_topic, sizeof(Settings.button_topic)); if (!payload) { - for(i = 1; i <= 4; i++) { + for(i = 1; i <= MAX_SWITCHES; i++) { send_button_power(1, i, 9); // Clear MQTT retain in broker } } - sysCfg.flag.mqtt_switch_retain = payload; + Settings.flag.mqtt_switch_retain = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_SWITCHRETAIN "\":\"%s\"}"), getStateText(sysCfg.flag.mqtt_switch_retain)); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_switch_retain)); } - else if (!strcasecmp_P(type, PSTR(D_CMND_POWERRETAIN))) { + else if (CMND_POWERRETAIN == command_code) { if ((payload >= 0) && (payload <= 1)) { if (!payload) { - for(i = 1; i <= Maxdevice; i++) { // Clear MQTT retain in broker - getTopic_P(stemp1, 1, sysCfg.mqtt_topic, getPowerDevice(scommand, i, sizeof(scommand))); + for(i = 1; i <= devices_present; i++) { // Clear MQTT retain in broker + GetTopic_P(stemp1, 1, Settings.mqtt_topic, GetPowerDevice(scommand, i, sizeof(scommand))); mqtt_data[0] = '\0'; - mqtt_publish(stemp1, sysCfg.flag.mqtt_power_retain); + MqttPublish(stemp1, Settings.flag.mqtt_power_retain); } } - sysCfg.flag.mqtt_power_retain = payload; + Settings.flag.mqtt_power_retain = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_POWERRETAIN "\":\"%s\"}"), getStateText(sysCfg.flag.mqtt_power_retain)); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_power_retain)); } - else if (!strcasecmp_P(type, PSTR(D_CMND_SENSORRETAIN))) { + else if (CMND_SENSORRETAIN == command_code) { if ((payload >= 0) && (payload <= 1)) { if (!payload) { mqtt_data[0] = '\0'; - mqtt_publish_topic_P(2, PSTR(D_RSLT_SENSOR), sysCfg.flag.mqtt_sensor_retain); + MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_ENERGY), Settings.flag.mqtt_sensor_retain); } - sysCfg.flag.mqtt_sensor_retain = payload; + Settings.flag.mqtt_sensor_retain = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_SENSORRETAIN "\":\"%s\"}"), getStateText(sysCfg.flag.mqtt_sensor_retain)); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_sensor_retain)); } #ifdef USE_DOMOTICZ - else if (domoticz_command(type, index, dataBuf, data_len, payload)) { + else if (DomoticzCommand(type, index, dataBuf, data_len, payload)) { // Serviced } #endif // USE_DOMOTICZ @@ -856,12 +769,12 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf, /********************************************************************************************/ -void mqttDataCb(char* topic, byte* data, unsigned int data_len) +void MqttDataCallback(char* topic, byte* data, unsigned int data_len) { char *str; - if (!strcmp(sysCfg.mqtt_prefix[0],sysCfg.mqtt_prefix[1])) { - str = strstr(topic,sysCfg.mqtt_prefix[0]); + if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1])) { + str = strstr(topic,Settings.mqtt_prefix[0]); if ((str == topic) && mqtt_cmnd_publish) { if (mqtt_cmnd_publish > 8) { mqtt_cmnd_publish -= 8; @@ -874,6 +787,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) char topicBuf[TOPSZ]; char dataBuf[data_len+1]; + char command [CMDSZ]; char stemp1[TOPSZ]; char *p; char *mtopic = NULL; @@ -899,19 +813,19 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_RESULT D_RECEIVED_TOPIC " %s, " D_DATA_SIZE " %d, " D_DATA " %s"), topicBuf, data_len, dataBuf); - addLog(LOG_LEVEL_DEBUG_MORE); + AddLog(LOG_LEVEL_DEBUG_MORE); // if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) Serial.println(dataBuf); #ifdef USE_DOMOTICZ - if (sysCfg.flag.mqtt_enabled) { - if (domoticz_mqttData(topicBuf, sizeof(topicBuf), dataBuf, sizeof(dataBuf))) { + if (Settings.flag.mqtt_enabled) { + if (DomoticzMqttData(topicBuf, sizeof(topicBuf), dataBuf, sizeof(dataBuf))) { return; } } #endif // USE_DOMOTICZ - grpflg = (strstr(topicBuf, sysCfg.mqtt_grptopic) != NULL); - fallbacktopic = (strstr(topicBuf, MQTTClient) != NULL); + grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != NULL); + fallback_topic_flag = (strstr(topicBuf, mqtt_client) != NULL); type = strrchr(topicBuf, '/') +1; // Last part of received topic is always the command (type) index = 1; @@ -930,11 +844,11 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_RESULT D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " %s, " D_DATA " %s"), grpflg, index, type, dataBuf); - addLog(LOG_LEVEL_DEBUG); + AddLog(LOG_LEVEL_DEBUG); if (type != NULL) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_COMMAND "\":\"" D_ERROR "\"}")); - if (sysCfg.ledstate &0x02) { + if (Settings.ledstate &0x02) { blinks++; } @@ -948,71 +862,72 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) payload = (int16_t) lnum; // -32766 - 32767 payload16 = (uint16_t) lnum; // 0 - 65535 } - blogdelay = MIN_BACKLOG_DELAY; // Reset backlog delay + backlog_delay = MIN_BACKLOG_DELAY; // Reset backlog delay - if (!strcasecmp_P(dataBuf, PSTR("OFF")) || !strcasecmp_P(dataBuf, PSTR(D_OFF)) || !strcasecmp_P(dataBuf, sysCfg.state_text[0]) || !strcasecmp_P(dataBuf, PSTR(D_FALSE)) || !strcasecmp_P(dataBuf, PSTR(D_STOP)) || !strcasecmp_P(dataBuf, PSTR(D_CELSIUS))) { + if ((GetCommandCode(command, sizeof(command), dataBuf, kOptionOff) >= 0) || !strcasecmp(dataBuf, Settings.state_text[0])) { payload = 0; } - if (!strcasecmp_P(dataBuf, PSTR("ON")) || !strcasecmp_P(dataBuf, PSTR(D_ON)) || !strcasecmp_P(dataBuf, sysCfg.state_text[1]) || !strcasecmp_P(dataBuf, PSTR(D_TRUE)) || !strcasecmp_P(dataBuf, PSTR(D_START)) || !strcasecmp_P(dataBuf, PSTR(D_FAHRENHEIT)) || !strcasecmp_P(dataBuf, PSTR(D_USER))) { + if ((GetCommandCode(command, sizeof(command), dataBuf, kOptionOn) >= 0) || !strcasecmp(dataBuf, Settings.state_text[1])) { payload = 1; } - if (!strcasecmp_P(dataBuf, PSTR("TOGGLE")) || !strcasecmp_P(dataBuf, PSTR(D_TOGGLE)) || !strcasecmp_P(dataBuf, sysCfg.state_text[2]) || !strcasecmp_P(dataBuf, PSTR(D_ADMIN))) { + if ((GetCommandCode(command, sizeof(command), dataBuf, kOptionToggle) >= 0) || !strcasecmp(dataBuf, Settings.state_text[2])) { payload = 2; } - if (!strcasecmp_P(dataBuf, PSTR("BLINK")) || !strcasecmp_P(dataBuf, PSTR(D_BLINK))) { + if (GetCommandCode(command, sizeof(command), dataBuf, kOptionBlink) >= 0) { payload = 3; } - if (!strcasecmp_P(dataBuf, PSTR("BLINKOFF")) || !strcasecmp_P(dataBuf, PSTR(D_BLINKOFF))) { + if (GetCommandCode(command, sizeof(command), dataBuf, kOptionBlinkOff) >= 0) { payload = 4; } // snprintf_P(log_data, sizeof(log_data), PSTR("RSLT: Payload %d, Payload16 %d"), payload, payload16); -// addLog(LOG_LEVEL_DEBUG); +// AddLog(LOG_LEVEL_DEBUG); - if (!strcasecmp_P(type, PSTR(D_CMND_BACKLOG))) { + int command_code = GetCommandCode(command, sizeof(command), type, kTasmotaCommands); + if (CMND_BACKLOG == command_code) { if (data_len) { char *blcommand = strtok(dataBuf, ";"); while (blcommand != NULL) { - Backlog[blogidx] = String(blcommand); - blogidx++; + backlog[backlog_index] = String(blcommand); + backlog_index++; /* - if (blogidx >= MAX_BACKLOG) { - blogidx = 0; + if (backlog_index >= MAX_BACKLOG) { + backlog_index = 0; } */ - blogidx &= 0xF; + backlog_index &= 0xF; blcommand = strtok(NULL, ";"); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_BACKLOG "\":\"" D_APPENDED "\"}")); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_APPENDED); } else { - uint8_t blflag = (blogptr == blogidx); - blogptr = blogidx; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_BACKLOG "\":\"%s\"}"), blflag ? D_EMPTY : D_ABORTED); + uint8_t blflag = (backlog_pointer == backlog_index); + backlog_pointer = backlog_index; + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, blflag ? D_EMPTY : D_ABORTED); } } - else if (!strcasecmp_P(type, PSTR(D_CMND_DELAY))) { + else if (CMND_DELAY == command_code) { if ((payload >= MIN_BACKLOG_DELAY) && (payload <= 3600)) { - blogdelay = payload; + backlog_delay = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DELAY "\":%d}"), blogdelay); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, backlog_delay); } - else if (!strcasecmp_P(type, PSTR(D_CMND_POWER)) && (index > 0) && (index <= Maxdevice)) { + else if ((CMND_POWER == command_code) && (index > 0) && (index <= devices_present)) { if ((payload < 0) || (payload > 4)) { payload = 9; } - do_cmnd_power(index, payload); - fallbacktopic = 0; + ExecuteCommandPower(index, payload); + fallback_topic_flag = 0; return; } - else if (!strcasecmp_P(type, PSTR(D_CMND_STATUS))) { + else if (CMND_STATUS == command_code) { if ((payload < 0) || (payload > MAX_STATUS)) { payload = 99; } - publish_status(payload); - fallbacktopic = 0; + PublishStatus(payload); + fallback_topic_flag = 0; return; } - else if ((sysCfg.module != MOTOR) && !strcasecmp_P(type, PSTR(D_CMND_POWERONSTATE))) { + else if ((CMND_POWERONSTATE == command_code) && (Settings.module != MOTOR)) { /* 0 = Keep relays off after power on * 1 = Turn relays on after power on * 2 = Toggle relays after power on @@ -1020,58 +935,58 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) * 4 = Turn relays on and disable any relay control (used for Sonoff Pow to always measure power) */ if ((payload >= 0) && (payload <= 4)) { - sysCfg.poweronstate = payload; - if (4 == sysCfg.poweronstate) { - for (byte i = 1; i <= Maxdevice; i++) { - do_cmnd_power(i, 1); + Settings.poweronstate = payload; + if (4 == Settings.poweronstate) { + for (byte i = 1; i <= devices_present; i++) { + ExecuteCommandPower(i, 1); } } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_POWERONSTATE "\":%d}"), sysCfg.poweronstate); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.poweronstate); } - else if (!strcasecmp_P(type, PSTR(D_CMND_PULSETIME)) && (index > 0) && (index <= MAX_PULSETIMERS)) { + else if ((CMND_PULSETIME == command_code) && (index > 0) && (index <= MAX_PULSETIMERS)) { if (data_len > 0) { - sysCfg.pulsetime[index -1] = payload16; // 0 - 65535 + Settings.pulse_timer[index -1] = payload16; // 0 - 65535 pulse_timer[index -1] = 0; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_PULSETIME "%d\":%d}"), index, sysCfg.pulsetime[index -1]); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, index, Settings.pulse_timer[index -1]); } - else if (!strcasecmp_P(type, PSTR(D_CMND_BLINKTIME))) { + else if (CMND_BLINKTIME == command_code) { if ((payload > 2) && (payload <= 3600)) { - sysCfg.blinktime = payload; + Settings.blinktime = payload; if (blink_timer) { - blink_timer = sysCfg.blinktime; + blink_timer = Settings.blinktime; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_BLINKTIME "\":%d}"), sysCfg.blinktime); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.blinktime); } - else if (!strcasecmp_P(type, PSTR(D_CMND_BLINKCOUNT))) { + else if (CMND_BLINKCOUNT == command_code) { if (data_len > 0) { - sysCfg.blinkcount = payload16; // 0 - 65535 + Settings.blinkcount = payload16; // 0 - 65535 if (blink_counter) { - blink_counter = sysCfg.blinkcount *2; + blink_counter = Settings.blinkcount *2; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_BLINKCOUNT "\":%d}"), sysCfg.blinkcount); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.blinkcount); } - else if (sfl_flg && sl_command(type, index, dataBuf, data_len, payload)) { + else if (light_type && LightCommand(type, index, dataBuf, data_len, payload)) { // Serviced } - else if (!strcasecmp_P(type, PSTR(D_CMND_SAVEDATA))) { + else if (CMND_SAVEDATA == command_code) { if ((payload >= 0) && (payload <= 3600)) { - sysCfg.savedata = payload; - savedatacounter = sysCfg.savedata; + Settings.save_data = payload; + save_data_counter = Settings.save_data; } - if (sysCfg.flag.savestate) { - sysCfg.power = power; + if (Settings.flag.save_state) { + Settings.power = power; } - CFG_Save(0); - if (sysCfg.savedata > 1) { - snprintf_P(stemp1, sizeof(stemp1), PSTR(D_EVERY " %d " D_UNIT_SECOND), sysCfg.savedata); + SettingsSave(0); + if (Settings.save_data > 1) { + snprintf_P(stemp1, sizeof(stemp1), PSTR(D_EVERY " %d " D_UNIT_SECOND), Settings.save_data); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_SAVEDATA "\":\"%s\"}"), (sysCfg.savedata > 1) ? stemp1 : getStateText(sysCfg.savedata)); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, (Settings.save_data > 1) ? stemp1 : GetStateText(Settings.save_data)); } - else if (!strcasecmp_P(type, PSTR(D_CMND_SETOPTION)) && ((index >= 0) && (index <= 14)) || ((index > 31) && (index <= P_MAX_PARAM8 +31))) { + else if ((CMND_SETOPTION == command_code) && ((index >= 0) && (index <= 17)) || ((index > 31) && (index <= P_MAX_PARAM8 +31))) { if (index <= 31) { ptype = 0; // SetOption0 .. 31 } else { @@ -1083,8 +998,9 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) if (payload <= 1) { switch (index) { case 3: // mqtt - restartflag = 2; - case 0: // savestate + case 15: // pwm_control + restart_flag = 2; + case 0: // save_state case 1: // button_restrict case 2: // value_units case 4: // mqtt_response @@ -1094,11 +1010,13 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) case 12: // stop_flash_rotate case 13: // button_single case 14: // interlock - bitWrite(sysCfg.flag.data, index, payload); + case 16: // ws_clock_reverse + case 17: // decimal_text + bitWrite(Settings.flag.data, index, payload); } if (12 == index) { // stop_flash_rotate stop_flash_rotate = payload; - CFG_Save(2); + SettingsSave(2); } } } @@ -1106,74 +1024,74 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) switch (index) { case P_HOLD_TIME: if ((payload >= 1) && (payload <= 100)) { - sysCfg.param[P_HOLD_TIME] = payload; + Settings.param[P_HOLD_TIME] = payload; } break; case P_MAX_POWER_RETRY: if ((payload >= 1) && (payload <= 250)) { - sysCfg.param[P_MAX_POWER_RETRY] = payload; + Settings.param[P_MAX_POWER_RETRY] = payload; } break; } } } if (ptype) { - snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), sysCfg.param[index]); + snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), Settings.param[index]); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_SETOPTION "%d\":\"%s\"}"), (ptype) ? index +32 : index, (ptype) ? stemp1 : getStateText(bitRead(sysCfg.flag.data, index))); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, (ptype) ? index +32 : index, (ptype) ? stemp1 : GetStateText(bitRead(Settings.flag.data, index))); } - else if (!strcasecmp_P(type, PSTR(D_CMND_TEMPERATURE_RESOLUTION))) { + else if (CMND_TEMPERATURE_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { - sysCfg.flag.temperature_resolution = payload; + Settings.flag.temperature_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_TEMPERATURE_RESOLUTION "\":%d}"), sysCfg.flag.temperature_resolution); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag.temperature_resolution); } - else if (!strcasecmp_P(type, PSTR(D_CMND_HUMIDITY_RESOLUTION))) { + else if (CMND_HUMIDITY_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { - sysCfg.flag.humidity_resolution = payload; + Settings.flag.humidity_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_HUMIDITY_RESOLUTION "\":%d}"), sysCfg.flag.humidity_resolution); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag.humidity_resolution); } - else if (!strcasecmp_P(type, PSTR(D_CMND_PRESSURE_RESOLUTION))) { + else if (CMND_PRESSURE_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { - sysCfg.flag.pressure_resolution = payload; + Settings.flag.pressure_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_PRESSURE_RESOLUTION "\":%d}"), sysCfg.flag.pressure_resolution); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag.pressure_resolution); } - else if (!strcasecmp_P(type, PSTR(D_CMND_POWER_RESOLUTION))) { + else if (CMND_POWER_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 1)) { - sysCfg.flag.wattage_resolution = payload; + Settings.flag.wattage_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_POWER_RESOLUTION "\":%d}"), sysCfg.flag.wattage_resolution); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag.wattage_resolution); } - else if (!strcasecmp_P(type, PSTR(D_CMND_VOLTAGE_RESOLUTION))) { + else if (CMND_VOLTAGE_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 1)) { - sysCfg.flag.voltage_resolution = payload; + Settings.flag.voltage_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_VOLTAGE_RESOLUTION "\":%d}"), sysCfg.flag.voltage_resolution); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag.voltage_resolution); } - else if (!strcasecmp_P(type, PSTR(D_CMND_ENERGY_RESOLUTION))) { + else if (CMND_ENERGY_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 5)) { - sysCfg.flag.energy_resolution = payload; + Settings.flag.energy_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_ENERGY_RESOLUTION "\":%d}"), sysCfg.flag.energy_resolution); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag.energy_resolution); } - else if (!strcasecmp_P(type, PSTR(D_CMND_MODULE))) { + else if (CMND_MODULE == command_code) { if ((payload > 0) && (payload <= MAXMODULE)) { payload--; - byte new_modflg = (sysCfg.module != payload); - sysCfg.module = payload; + byte new_modflg = (Settings.module != payload); + Settings.module = payload; if (new_modflg) { for (byte i = 0; i < MAX_GPIO_PIN; i++) { - sysCfg.my_module.gp.io[i] = 0; + Settings.my_gp.io[i] = 0; } } - restartflag = 2; + restart_flag = 2; } - snprintf_P(stemp1, sizeof(stemp1), modules[sysCfg.module].name); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MODULE "\":\"%d (%s)\"}"), sysCfg.module +1, stemp1); + snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, Settings.module +1, stemp1); } - else if (!strcasecmp_P(type, PSTR(D_CMND_MODULES))) { + else if (CMND_MODULES == command_code) { for (byte i = 0; i < MAXMODULE; i++) { if (!jsflg) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MODULES "%d\":\""), lines); @@ -1181,28 +1099,28 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, "), mqtt_data); } jsflg = 1; - snprintf_P(stemp1, sizeof(stemp1), modules[i].name); + snprintf_P(stemp1, sizeof(stemp1), kModules[i].name); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%d (%s)"), mqtt_data, i +1, stemp1); if ((strlen(mqtt_data) > 200) || (i == MAXMODULE -1)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); - mqtt_publish_topic_P(5, type); + MqttPublishPrefixTopic_P(5, type); jsflg = 0; lines++; } } mqtt_data[0] = '\0'; } - else if (!strcasecmp_P(type, PSTR(D_CMND_GPIO)) && (index < MAX_GPIO_PIN)) { + else if ((CMND_GPIO == command_code) && (index < MAX_GPIO_PIN)) { mytmplt cmodule; - memcpy_P(&cmodule, &modules[sysCfg.module], sizeof(cmodule)); + memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); if ((GPIO_USER == cmodule.gp.io[index]) && (payload >= 0) && (payload < GPIO_SENSOR_END)) { for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if ((GPIO_USER == cmodule.gp.io[i]) && (sysCfg.my_module.gp.io[i] == payload)) { - sysCfg.my_module.gp.io[i] = 0; + if ((GPIO_USER == cmodule.gp.io[i]) && (Settings.my_gp.io[i] == payload)) { + Settings.my_gp.io[i] = 0; } } - sysCfg.my_module.gp.io[index] = payload; - restartflag = 2; + Settings.my_gp.io[index] = payload; + restart_flag = 2; } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); byte jsflg = 0; @@ -1212,17 +1130,17 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, "), mqtt_data); } jsflg = 1; - snprintf_P(stemp1, sizeof(stemp1), sensors[sysCfg.my_module.gp.io[i]]); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_GPIO "%d\":%d (%s)"), mqtt_data, i, sysCfg.my_module.gp.io[i], stemp1); + snprintf_P(stemp1, sizeof(stemp1), kSensors[Settings.my_gp.io[i]]); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_GPIO "%d\":\"%d (%s)\""), mqtt_data, i, Settings.my_gp.io[i], stemp1); } } if (jsflg) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_GPIO "\":\"" D_NOT_SUPPORTED "\"}")); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_NOT_SUPPORTED); } } - else if (!strcasecmp_P(type, PSTR(D_CMND_GPIOS))) { + else if (CMND_GPIOS == command_code) { for (byte i = 0; i < GPIO_SENSOR_END; i++) { if (!jsflg) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_GPIOS "%d\":\""), lines); @@ -1230,333 +1148,358 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, "), mqtt_data); } jsflg = 1; - snprintf_P(stemp1, sizeof(stemp1), sensors[i]); + snprintf_P(stemp1, sizeof(stemp1), kSensors[i]); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%d (%s)"), mqtt_data, i, stemp1); if ((strlen(mqtt_data) > 200) || (i == GPIO_SENSOR_END -1)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); - mqtt_publish_topic_P(5, type); + MqttPublishPrefixTopic_P(5, type); jsflg = 0; lines++; } } mqtt_data[0] = '\0'; } - else if (!strcasecmp_P(type, PSTR(D_CMND_PWM)) && (index > pwm_idxoffset) && (index <= 5)) { - if ((payload >= 0) && (payload <= PWM_RANGE) && (pin[GPIO_PWM1 + index -1] < 99)) { - sysCfg.pwmvalue[index -1] = payload; - analogWrite(pin[GPIO_PWM1 + index -1], payload); + else if ((CMND_PWM == command_code) && !light_type && (index > 0) && (index <= MAX_PWMS)) { + if ((payload >= 0) && (payload <= Settings.pwm_range) && (pin[GPIO_PWM1 + index -1] < 99)) { + Settings.pwm_value[index -1] = payload; + analogWrite(pin[GPIO_PWM1 + index -1], bitRead(pwm_inverted, index -1) ? Settings.pwm_range - payload : payload); } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_PWM "\":{")); bool first = true; - for (byte i = 0; i < 5; i++) { + for (byte i = 0; i < MAX_PWMS; i++) { if(pin[GPIO_PWM1 + i] < 99) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_PWM "%d\":%d"), mqtt_data, first ? "" : ", ", i+1, sysCfg.pwmvalue[i]); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_PWM "%d\":%d"), mqtt_data, first ? "" : ", ", i+1, Settings.pwm_value[i]); first = false; } } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}}"),mqtt_data); } - else if (!strcasecmp_P(type, PSTR(D_CMND_COUNTER)) && (index > 0) && (index <= MAX_COUNTERS)) { - if ((data_len > 0) && (pin[GPIO_CNTR1 + index -1] < 99)) { - rtcMem.pCounter[index -1] = payload16; - sysCfg.pCounter[index -1] = payload16; + else if (CMND_PWMFREQUENCY == command_code) { + if ((1 == payload) || ((payload >= 100) && (payload <= 4000))) { + Settings.pwm_frequency = (1 == payload) ? PWM_FREQ : payload; + analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c) } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_COUNTER "%d\":%d}"), index, rtcMem.pCounter[index -1]); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.pwm_frequency); } - else if (!strcasecmp_P(type, PSTR(D_CMND_COUNTERTYPE)) && (index > 0) && (index <= MAX_COUNTERS)) { - if ((payload >= 0) && (payload <= 1) && (pin[GPIO_CNTR1 + index -1] < 99)) { - bitWrite(sysCfg.pCounterType, index -1, payload &1); - rtcMem.pCounter[index -1] = 0; - sysCfg.pCounter[index -1] = 0; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_COUNTERTYPE "%d\":%d}"), index, bitRead(sysCfg.pCounterType, index -1)); - } - else if (!strcasecmp_P(type, PSTR(D_CMND_COUNTERDEBOUNCE))) { - if ((data_len > 0) && (payload16 < 32001)) { - sysCfg.pCounterDebounce = payload16; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_COUNTERDEBOUNCE "\":%d}"), sysCfg.pCounterDebounce); - } - else if (!strcasecmp_P(type, PSTR(D_CMND_SLEEP))) { - if ((payload >= 0) && (payload < 251)) { - if ((!sysCfg.sleep && payload) || (sysCfg.sleep && !payload)) { - restartflag = 2; + else if (CMND_PWMRANGE == command_code) { + if ((1 == payload) || ((payload > 254) && (payload < 1024))) { + Settings.pwm_range = (1 == payload) ? PWM_RANGE : payload; + for (byte i; i < MAX_PWMS; i++) { + if (Settings.pwm_value[i] > Settings.pwm_range) { + Settings.pwm_value[i] = Settings.pwm_range; + } } - sysCfg.sleep = payload; + analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h) + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.pwm_range); + } + else if ((CMND_COUNTER == command_code) && (index > 0) && (index <= MAX_COUNTERS)) { + if ((data_len > 0) && (pin[GPIO_CNTR1 + index -1] < 99)) { + RtcSettings.pulse_counter[index -1] = payload16; + Settings.pulse_counter[index -1] = payload16; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, index, RtcSettings.pulse_counter[index -1]); + } + else if ((CMND_COUNTERTYPE == command_code) && (index > 0) && (index <= MAX_COUNTERS)) { + if ((payload >= 0) && (payload <= 1) && (pin[GPIO_CNTR1 + index -1] < 99)) { + bitWrite(Settings.pulse_counter_type, index -1, payload &1); + RtcSettings.pulse_counter[index -1] = 0; + Settings.pulse_counter[index -1] = 0; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, index, bitRead(Settings.pulse_counter_type, index -1)); + } + else if (CMND_COUNTERDEBOUNCE == command_code) { + if ((data_len > 0) && (payload16 < 32001)) { + Settings.pulse_counter_debounce = payload16; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.pulse_counter_debounce); + } + else if (CMND_SLEEP == command_code) { + if ((payload >= 0) && (payload < 251)) { + if ((!Settings.sleep && payload) || (Settings.sleep && !payload)) { + restart_flag = 2; + } + Settings.sleep = payload; sleep = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_SLEEP "\":\"%d%s (%d%s)\"}"), sleep, (sysCfg.flag.value_units) ? " " D_UNIT_MILLISECOND : "", sysCfg.sleep, (sysCfg.flag.value_units) ? " " D_UNIT_MILLISECOND : ""); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_UNIT_NVALUE_UNIT, command, sleep, (Settings.flag.value_units) ? " " D_UNIT_MILLISECOND : "", Settings.sleep, (Settings.flag.value_units) ? " " D_UNIT_MILLISECOND : ""); } - else if (!strcasecmp_P(type, PSTR(D_CMND_UPGRADE)) || !strcasecmp_P(type, PSTR(D_CMND_UPLOAD))) { + else if ((CMND_UPGRADE == command_code) || (CMND_UPLOAD == command_code)) { // Check if the payload is numerically 1, and had no trailing chars. // e.g. "1foo" or "1.2.3" could fool us. // Check if the version we have been asked to upgrade to is higher than our current version. // We also need at least 3 chars to make a valid version number string. - if (((1 == data_len) && (1 == payload)) || ((data_len >= 3) && newerVersion(dataBuf))) { - otaflag = 3; - snprintf_P(mqtt_data, sizeof(mqtt_data), "{\"" D_CMND_UPGRADE "\":\"" D_VERSION " %s " D_FROM " %s\"}", Version, sysCfg.otaUrl); + if (((1 == data_len) && (1 == payload)) || ((data_len >= 3) && NewerVersion(dataBuf))) { + ota_state_flag = 3; + snprintf_P(mqtt_data, sizeof(mqtt_data), "{\"%s\":\"" D_VERSION " %s " D_FROM " %s\"}", command, version, Settings.ota_url); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), "{\"" D_CMND_UPGRADE "\":\"" D_ONE_OR_GT "\"}", Version); + snprintf_P(mqtt_data, sizeof(mqtt_data), "{\"%s\":\"" D_ONE_OR_GT "\"}", command, version); } } - else if (!strcasecmp_P(type, PSTR(D_CMND_OTAURL))) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.otaUrl))) - strlcpy(sysCfg.otaUrl, (1 == payload) ? OTA_URL : dataBuf, sizeof(sysCfg.otaUrl)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_OTAURL "\":\"%s\"}"), sysCfg.otaUrl); + else if (CMND_OTAURL == command_code) { + if ((data_len > 0) && (data_len < sizeof(Settings.ota_url))) + strlcpy(Settings.ota_url, (1 == payload) ? OTA_URL : dataBuf, sizeof(Settings.ota_url)); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.ota_url); } - else if (!strcasecmp_P(type, PSTR(D_CMND_SERIALLOG))) { + else if (CMND_SERIALLOG == command_code) { if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) { - sysCfg.seriallog_level = payload; + Settings.seriallog_level = payload; seriallog_level = payload; seriallog_timer = 0; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_SERIALLOG "\":\"%d (" D_ACTIVE " %d)\"}"), sysCfg.seriallog_level, seriallog_level); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, command, Settings.seriallog_level, seriallog_level); } - else if (!strcasecmp_P(type, PSTR(D_CMND_SYSLOG))) { + else if (CMND_SYSLOG == command_code) { if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) { - sysCfg.syslog_level = payload; - syslog_level = (sysCfg.flag.emulation) ? 0 : payload; + Settings.syslog_level = payload; + syslog_level = (Settings.flag.emulation) ? 0 : payload; syslog_timer = 0; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_SYSLOG "\":\"%d (" D_ACTIVE " %d)\"}"), sysCfg.syslog_level, syslog_level); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, command, Settings.syslog_level, syslog_level); } - else if (!strcasecmp_P(type, PSTR(D_CMND_LOGHOST))) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.syslog_host))) { - strlcpy(sysCfg.syslog_host, (1 == payload) ? SYS_LOG_HOST : dataBuf, sizeof(sysCfg.syslog_host)); + else if (CMND_LOGHOST == command_code) { + if ((data_len > 0) && (data_len < sizeof(Settings.syslog_host))) { + strlcpy(Settings.syslog_host, (1 == payload) ? SYS_LOG_HOST : dataBuf, sizeof(Settings.syslog_host)); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_LOGHOST "\":\"%s\"}"), sysCfg.syslog_host); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.syslog_host); } - else if (!strcasecmp_P(type, PSTR(D_CMND_LOGPORT))) { + else if (CMND_LOGPORT == command_code) { if (payload16 > 0) { - sysCfg.syslog_port = (1 == payload16) ? SYS_LOG_PORT : payload16; + Settings.syslog_port = (1 == payload16) ? SYS_LOG_PORT : payload16; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_LOGPORT "\":%d}"), sysCfg.syslog_port); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.syslog_port); } - else if (!strcasecmp_P(type, PSTR(D_CMND_IPADDRESS)) && (index > 0) && (index <= 4)) { - if (parseIP(&address, dataBuf)) { - sysCfg.ip_address[index -1] = address; -// restartflag = 2; + else if ((CMND_IPADDRESS == command_code) && (index > 0) && (index <= 4)) { + if (ParseIp(&address, dataBuf)) { + Settings.ip_address[index -1] = address; +// restart_flag = 2; } snprintf_P(stemp1, sizeof(stemp1), PSTR(" (%s)"), WiFi.localIP().toString().c_str()); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IPADDRESS "%d\":\"%s%s\"}"), index, IPAddress(sysCfg.ip_address[index -1]).toString().c_str(), (1 == index) ? stemp1:""); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE_SVALUE, command, index, IPAddress(Settings.ip_address[index -1]).toString().c_str(), (1 == index) ? stemp1:""); } - else if (!strcasecmp_P(type, PSTR(D_CMND_NTPSERVER)) && (index > 0) && (index <= 3)) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.ntp_server[0]))) { - strlcpy(sysCfg.ntp_server[index -1], (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? (1==index)?NTP_SERVER1:(2==index)?NTP_SERVER2:NTP_SERVER3 : dataBuf, sizeof(sysCfg.ntp_server[0])); - for (i = 0; i < strlen(sysCfg.ntp_server[index -1]); i++) { - if (sysCfg.ntp_server[index -1][i] == ',') { - sysCfg.ntp_server[index -1][i] = '.'; + else if ((CMND_NTPSERVER == command_code) && (index > 0) && (index <= 3)) { + if ((data_len > 0) && (data_len < sizeof(Settings.ntp_server[0]))) { + strlcpy(Settings.ntp_server[index -1], (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? (1==index)?NTP_SERVER1:(2==index)?NTP_SERVER2:NTP_SERVER3 : dataBuf, sizeof(Settings.ntp_server[0])); + for (i = 0; i < strlen(Settings.ntp_server[index -1]); i++) { + if (Settings.ntp_server[index -1][i] == ',') { + Settings.ntp_server[index -1][i] = '.'; } } - restartflag = 2; + restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_NTPSERVER "%d\":\"%s\"}"), index, sysCfg.ntp_server[index -1]); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.ntp_server[index -1]); } - else if (!strcasecmp_P(type, PSTR(D_CMND_AP))) { + else if (CMND_AP == command_code) { if ((payload >= 0) && (payload <= 2)) { switch (payload) { case 0: // Toggle - sysCfg.sta_active ^= 1; + Settings.sta_active ^= 1; break; case 1: // AP1 case 2: // AP2 - sysCfg.sta_active = payload -1; + Settings.sta_active = payload -1; } - restartflag = 2; + restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_AP "\":\"%d (%s)\"}"), sysCfg.sta_active +1, sysCfg.sta_ssid[sysCfg.sta_active]); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active]); } - else if (!strcasecmp_P(type, PSTR(D_CMND_SSID)) && (index > 0) && (index <= 2)) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.sta_ssid[0]))) { - strlcpy(sysCfg.sta_ssid[index -1], (1 == payload) ? (1 == index) ? STA_SSID1 : STA_SSID2 : dataBuf, sizeof(sysCfg.sta_ssid[0])); - sysCfg.sta_active = index -1; - restartflag = 2; + else if ((CMND_SSID == command_code) && (index > 0) && (index <= 2)) { + if ((data_len > 0) && (data_len < sizeof(Settings.sta_ssid[0]))) { + strlcpy(Settings.sta_ssid[index -1], (1 == payload) ? (1 == index) ? STA_SSID1 : STA_SSID2 : dataBuf, sizeof(Settings.sta_ssid[0])); + Settings.sta_active = index -1; + restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_SSID "%d\":\"%s\"}"), index, sysCfg.sta_ssid[index -1]); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.sta_ssid[index -1]); } - else if (!strcasecmp_P(type, PSTR(D_CMND_PASSWORD)) && (index > 0) && (index <= 2)) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.sta_pwd[0]))) { - strlcpy(sysCfg.sta_pwd[index -1], (1 == payload) ? (1 == index) ? STA_PASS1 : STA_PASS2 : dataBuf, sizeof(sysCfg.sta_pwd[0])); - sysCfg.sta_active = index -1; - restartflag = 2; + else if ((CMND_PASSWORD == command_code) && (index > 0) && (index <= 2)) { + if ((data_len > 0) && (data_len < sizeof(Settings.sta_pwd[0]))) { + strlcpy(Settings.sta_pwd[index -1], (1 == payload) ? (1 == index) ? STA_PASS1 : STA_PASS2 : dataBuf, sizeof(Settings.sta_pwd[0])); + Settings.sta_active = index -1; + restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_PASSWORD "%d\":\"%s\"}"), index, sysCfg.sta_pwd[index -1]); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.sta_pwd[index -1]); } - else if (!grpflg && !strcasecmp_P(type, PSTR(D_CMND_HOSTNAME))) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.hostname))) { - strlcpy(sysCfg.hostname, (1 == payload) ? WIFI_HOSTNAME : dataBuf, sizeof(sysCfg.hostname)); - if (strstr(sysCfg.hostname,"%")) { - strlcpy(sysCfg.hostname, WIFI_HOSTNAME, sizeof(sysCfg.hostname)); + else if ((CMND_HOSTNAME == command_code) && !grpflg) { + if ((data_len > 0) && (data_len < sizeof(Settings.hostname))) { + strlcpy(Settings.hostname, (1 == payload) ? WIFI_HOSTNAME : dataBuf, sizeof(Settings.hostname)); + if (strstr(Settings.hostname,"%")) { + strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); } - restartflag = 2; + restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_HOSTNAME "\":\"%s\"}"), sysCfg.hostname); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.hostname); } - else if (!strcasecmp_P(type, PSTR(D_CMND_WIFICONFIG))) { + else if (CMND_WIFICONFIG == command_code) { if ((payload >= WIFI_RESTART) && (payload < MAX_WIFI_OPTION)) { - sysCfg.sta_config = payload; - wificheckflag = sysCfg.sta_config; - snprintf_P(stemp1, sizeof(stemp1), wificfg[sysCfg.sta_config]); + Settings.sta_config = payload; + wifi_state_flag = Settings.sta_config; + snprintf_P(stemp1, sizeof(stemp1), kWifiConfig[Settings.sta_config]); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WIFICONFIG "\":\"%s " D_SELECTED "\"}"), stemp1); - if (WIFI_State() != WIFI_RESTART) { + if (WifiState() != WIFI_RESTART) { // snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s after restart"), mqtt_data); - restartflag = 2; + restart_flag = 2; } } else { - snprintf_P(stemp1, sizeof(stemp1), wificfg[sysCfg.sta_config]); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WIFICONFIG "\":\"%d (%s)\"}"), sysCfg.sta_config, stemp1); + snprintf_P(stemp1, sizeof(stemp1), kWifiConfig[Settings.sta_config]); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, Settings.sta_config, stemp1); } } - else if (!strcasecmp_P(type, PSTR(D_CMND_FRIENDLYNAME)) && (index > 0) && (index <= 4)) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.friendlyname[0]))) { + else if ((CMND_FRIENDLYNAME == command_code) && (index > 0) && (index <= 4)) { + if ((data_len > 0) && (data_len < sizeof(Settings.friendlyname[0]))) { if (1 == index) { snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME)); } else { snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME "%d"), index); } - strlcpy(sysCfg.friendlyname[index -1], (1 == payload) ? stemp1 : dataBuf, sizeof(sysCfg.friendlyname[index -1])); + strlcpy(Settings.friendlyname[index -1], (1 == payload) ? stemp1 : dataBuf, sizeof(Settings.friendlyname[index -1])); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_FRIENDLYNAME "%d\":\"%s\"}"), index, sysCfg.friendlyname[index -1]); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.friendlyname[index -1]); } - else if (!strcasecmp_P(type, PSTR(D_CMND_SWITCHMODE)) && (index > 0) && (index <= 4)) { + else if ((CMND_SWITCHMODE == command_code) && (index > 0) && (index <= MAX_SWITCHES)) { if ((payload >= 0) && (payload < MAX_SWITCH_OPTION)) { - sysCfg.switchmode[index -1] = payload; + Settings.switchmode[index -1] = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_SWITCHMODE "%d\":%d}"), index, sysCfg.switchmode[index-1]); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, index, Settings.switchmode[index-1]); } #ifdef USE_WEBSERVER - else if (!strcasecmp_P(type, PSTR(D_CMND_WEBSERVER))) { + else if (CMND_WEBSERVER == command_code) { if ((payload >= 0) && (payload <= 2)) { - sysCfg.webserver = payload; + Settings.webserver = payload; } - if (sysCfg.webserver) { + if (Settings.webserver) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WEBSERVER "\":\"" D_ACTIVE_FOR " %s " D_ON_DEVICE " %s " D_WITH_IP_ADDRESS " %s\"}"), - (2 == sysCfg.webserver) ? D_ADMIN : D_USER, Hostname, WiFi.localIP().toString().c_str()); + (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str()); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WEBSERVER "\":\"%s\"}"), getStateText(0)); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(0)); } } - else if (!strcasecmp_P(type, PSTR(D_CMND_WEBPASSWORD))) { - if ((data_len > 0) && (data_len < sizeof(sysCfg.web_password))) { - strlcpy(sysCfg.web_password, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? WEB_PASSWORD : dataBuf, sizeof(sysCfg.web_password)); + else if (CMND_WEBPASSWORD == command_code) { + if ((data_len > 0) && (data_len < sizeof(Settings.web_password))) { + strlcpy(Settings.web_password, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? WEB_PASSWORD : dataBuf, sizeof(Settings.web_password)); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WEBPASSWORD "\":\"%s\"}"), sysCfg.web_password); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.web_password); } - else if (!strcasecmp_P(type, PSTR(D_CMND_WEBLOG))) { + else if (CMND_WEBLOG == command_code) { if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) { - sysCfg.weblog_level = payload; + Settings.weblog_level = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WEBLOG "\":%d}"), sysCfg.weblog_level); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.weblog_level); } #ifdef USE_EMULATION - else if (!strcasecmp_P(type, PSTR(D_CMND_EMULATION))) { - if ((payload >= 0) && (payload <= 2)) { - sysCfg.flag.emulation = payload; - restartflag = 2; + else if (CMND_EMULATION == command_code) { + if ((payload >= EMUL_NONE) && (payload < EMUL_MAX)) { + Settings.flag.emulation = payload; + restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_EMULATION "\":%d}"), sysCfg.flag.emulation); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag.emulation); } #endif // USE_EMULATION #endif // USE_WEBSERVER - else if (!strcasecmp_P(type, PSTR(D_CMND_TELEPERIOD))) { + else if (CMND_TELEPERIOD == command_code) { if ((payload >= 0) && (payload < 3601)) { - sysCfg.tele_period = (1 == payload) ? TELE_PERIOD : payload; - if ((sysCfg.tele_period > 0) && (sysCfg.tele_period < 10)) { - sysCfg.tele_period = 10; // Do not allow periods < 10 seconds + Settings.tele_period = (1 == payload) ? TELE_PERIOD : payload; + if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) { + Settings.tele_period = 10; // Do not allow periods < 10 seconds } - tele_period = sysCfg.tele_period; + tele_period = Settings.tele_period; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_TELEPERIOD "\":\"%d%s\"}"), sysCfg.tele_period, (sysCfg.flag.value_units) ? " " D_UNIT_SECOND : ""); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_UNIT, command, Settings.tele_period, (Settings.flag.value_units) ? " " D_UNIT_SECOND : ""); } - else if (!strcasecmp_P(type, PSTR(D_CMND_RESTART))) { + else if (CMND_RESTART == command_code) { switch (payload) { case 1: - restartflag = 2; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESTART "\":\"" D_RESTARTING "\"}")); + restart_flag = 2; + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_RESTARTING); break; case 99: - addLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); ESP.restart(); break; default: - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESTART "\":\"" D_ONE_TO_RESTART "\"}")); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_ONE_TO_RESTART); } } - else if (!strcasecmp_P(type, PSTR(D_CMND_RESET))) { + else if (CMND_RESET == command_code) { switch (payload) { case 1: - restartflag = 211; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_RESET_AND_RESTARTING "\"}")); + restart_flag = 211; + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command , D_RESET_AND_RESTARTING); break; case 2: - restartflag = 212; + restart_flag = 212; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_ERASE ", " D_RESET_AND_RESTARTING "\"}")); break; default: - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_ONE_TO_RESET "\"}")); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_ONE_TO_RESET); } } - else if (!strcasecmp_P(type, PSTR(D_CMND_TIMEZONE))) { - if ((data_len > 0) && (((payload >= -12) && (payload <= 12)) || (99 == payload))) { - sysCfg.timezone = payload; + else if (CMND_TIMEZONE == command_code) { + if ((data_len > 0) && (((payload >= -13) && (payload <= 13)) || (99 == payload))) { + Settings.timezone = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_TIMEZONE "\":%d}"), sysCfg.timezone); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.timezone); } - else if (!strcasecmp_P(type, PSTR(D_CMND_LEDPOWER))) { + else if (CMND_ALTITUDE == command_code) { + if ((data_len > 0) && ((payload >= -30000) && (payload <= 30000))) { + Settings.altitude = payload; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.altitude); + } + else if (CMND_LEDPOWER == command_code) { if ((payload >= 0) && (payload <= 2)) { - sysCfg.ledstate &= 8; + Settings.ledstate &= 8; switch (payload) { case 0: // Off case 1: // On - sysCfg.ledstate = payload << 3; + Settings.ledstate = payload << 3; break; case 2: // Toggle - sysCfg.ledstate ^= 8; + Settings.ledstate ^= 8; break; } blinks = 0; - setLed(sysCfg.ledstate &8); + SetLedPower(Settings.ledstate &8); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_LEDPOWER "\":\"%s\"}"), getStateText(bitRead(sysCfg.ledstate, 3))); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(bitRead(Settings.ledstate, 3))); } - else if (!strcasecmp_P(type, PSTR(D_CMND_LEDSTATE))) { + else if (CMND_LEDSTATE ==command_code) { if ((payload >= 0) && (payload < MAX_LED_OPTION)) { - sysCfg.ledstate = payload; - if (!sysCfg.ledstate) { - setLed(0); + Settings.ledstate = payload; + if (!Settings.ledstate) { + SetLedPower(0); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_LEDSTATE "\":%d}"), sysCfg.ledstate); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.ledstate); } - else if (!strcasecmp_P(type, PSTR(D_CMND_CFGDUMP))) { - CFG_Dump(dataBuf); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_CFGDUMP "\":\"" D_DONE "\"}")); + else if (CMND_CFGDUMP == command_code) { + SettingsDump(dataBuf); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_DONE); } - else if (sysCfg.flag.mqtt_enabled && mqtt_command(grpflg, type, index, dataBuf, data_len, payload, payload16)) { + else if (Settings.flag.mqtt_enabled && MqttCommand(grpflg, type, index, dataBuf, data_len, payload, payload16)) { // Serviced } - else if (hlw_flg && hlw_command(type, index, dataBuf, data_len, payload)) { + else if (hlw_flg && HlwCommand(type, index, dataBuf, data_len, payload)) { // Serviced } - else if ((SONOFF_BRIDGE == sysCfg.module) && sb_command(type, index, dataBuf, data_len, payload)) { + else if ((SONOFF_BRIDGE == Settings.module) && SonoffBridgeCommand(type, index, dataBuf, data_len, payload)) { // Serviced } #ifdef USE_I2C - else if (i2c_flg && !strcasecmp_P(type, PSTR(D_CMND_I2CSCAN))) { - i2c_scan(mqtt_data, sizeof(mqtt_data)); + else if ((CMND_I2CSCAN == command_code) && i2c_flg) { + I2cScan(mqtt_data, sizeof(mqtt_data)); } #endif // USE_I2C #ifdef USE_IR_REMOTE - else if ((pin[GPIO_IRSEND] < 99) && ir_send_command(type, index, dataBuf, data_len, payload)) { + else if ((pin[GPIO_IRSEND] < 99) && IrSendCommand(type, index, dataBuf, data_len, payload)) { // Serviced } #endif // USE_IR_REMOTE #ifdef DEBUG_THEO - else if (!strcasecmp_P(type, PSTR(D_CMND_EXCEPTION))) { + else if (CMND_EXCEPTION == command_code) { if (data_len > 0) { - exception_tst(payload); + ExceptionTest(payload); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_EXCEPTION "\":\"" D_DONE "\"}")); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_DONE); } #endif // DEBUG_THEO else { @@ -1570,9 +1513,9 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) type = (char*)topicBuf; } if (mqtt_data[0] != '\0') { - mqtt_publish_topic_P(5, type); + MqttPublishPrefixTopic_P(5, type); } - fallbacktopic = 0; + fallback_topic_flag = 0; } /********************************************************************************************/ @@ -1592,43 +1535,37 @@ boolean send_button_power(byte key, byte device, byte state) char stemp1[10]; boolean result = false; - char *key_topic = (key) ? sysCfg.switch_topic : sysCfg.button_topic; - if (sysCfg.flag.mqtt_enabled && mqttClient.connected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { - if (!key && (device > Maxdevice)) { + char *key_topic = (key) ? Settings.switch_topic : Settings.button_topic; + if (Settings.flag.mqtt_enabled && MqttClient.connected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { + if (!key && (device > devices_present)) { device = 1; } - -// snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), device); -// snprintf_P(scommand, sizeof(scommand), PSTR("POWER%s"), (key || (Maxdevice > 1)) ? stemp1 : ""); -// getTopic_P(stopic, 0, key_topic, scommand); - - getTopic_P(stopic, 0, key_topic, getPowerDevice(scommand, device, sizeof(scommand), key)); - + GetTopic_P(stopic, 0, key_topic, GetPowerDevice(scommand, device, sizeof(scommand), key)); if (9 == state) { mqtt_data[0] = '\0'; } else { - if ((!strcmp(sysCfg.mqtt_topic, key_topic) || !strcmp(sysCfg.mqtt_grptopic, key_topic)) && (2 == state)) { - state = ~(power >> (device -1)) & 0x01; + if ((!strcmp(Settings.mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic)) && (2 == state)) { + state = ~(power >> (device -1)) &1; } - snprintf_P(mqtt_data, sizeof(mqtt_data), getStateText(state)); + snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(state)); } #ifdef USE_DOMOTICZ - if (!(domoticz_button(key, device, state, strlen(mqtt_data)))) { - mqtt_publish_sec(stopic, (key) ? sysCfg.flag.mqtt_switch_retain : sysCfg.flag.mqtt_button_retain); + if (!(DomoticzButton(key, device, state, strlen(mqtt_data)))) { + MqttPublishDirect(stopic, (key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain); } #else - mqtt_publish_sec(stopic, (key) ? sysCfg.flag.mqtt_switch_retain : sysCfg.flag.mqtt_button_retain); + MqttPublishDirect(stopic, (key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain); #endif // USE_DOMOTICZ result = true; } return result; } -void do_cmnd_power(byte device, byte state) +void ExecuteCommandPower(byte device, byte state) { // device = Relay number 1 and up // state 0 = Relay Off -// state 1 = Relay On (turn off after sysCfg.pulsetime * 100 mSec if enabled) +// state 1 = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled) // state 2 = Toggle relay // state 3 = Blink relay // state 4 = Stop blinking relay @@ -1636,34 +1573,36 @@ void do_cmnd_power(byte device, byte state) // state 7 = Relay On and no publishPowerState // state 9 = Show power state - uint8_t publishPower = 1; + uint8_t publish_power = 1; if ((6 == state) || (7 == state)) { state &= 1; - publishPower = 0; + publish_power = 0; } - if ((device < 1) || (device > Maxdevice)) { + if ((device < 1) || (device > devices_present)) { device = 1; } - byte mask = 0x01 << (device -1); - pulse_timer[(device -1)&3] = 0; + if (device <= MAX_PULSETIMERS) { + pulse_timer[(device -1)] = 0; + } + power_t mask = 1 << (device -1); if (state <= 2) { if ((blink_mask & mask)) { - blink_mask &= (0xFF ^ mask); // Clear device mask - mqtt_publishPowerBlinkState(device); + blink_mask &= (POWER_MASK ^ mask); // Clear device mask + MqttPublishPowerBlinkState(device); } - if (sysCfg.flag.interlock && !interlockmutex) { // Clear all but masked relay - interlockmutex = 1; - for (byte i = 0; i < Maxdevice; i++) { - byte imask = 0x01 << i; + if (Settings.flag.interlock && !interlock_mutex) { // Clear all but masked relay + interlock_mutex = 1; + for (byte i = 0; i < devices_present; i++) { + power_t imask = 1 << i; if ((power & imask) && (mask != imask)) { - do_cmnd_power(i +1, 0); + ExecuteCommandPower(i +1, 0); } } - interlockmutex = 0; + interlock_mutex = 0; } switch (state) { case 0: { // Off - power &= (0xFF ^ mask); + power &= (POWER_MASK ^ mask); break; } case 1: // On power |= mask; @@ -1671,52 +1610,54 @@ void do_cmnd_power(byte device, byte state) case 2: // Toggle power ^= mask; } - setRelay(power); + SetDevicePower(power); #ifdef USE_DOMOTICZ - domoticz_updatePowerState(device); + DomoticzUpdatePowerState(device); #endif // USE_DOMOTICZ - pulse_timer[(device -1)&3] = (power & mask) ? sysCfg.pulsetime[(device -1)&3] : 0; + if (device <= MAX_PULSETIMERS) { + pulse_timer[(device -1)] = (power & mask) ? Settings.pulse_timer[(device -1)] : 0; + } } else if (3 == state) { // Blink if (!(blink_mask & mask)) { - blink_powersave = (blink_powersave & (0xFF ^ mask)) | (power & mask); // Save state + blink_powersave = (blink_powersave & (POWER_MASK ^ mask)) | (power & mask); // Save state blink_power = (power >> (device -1))&1; // Prep to Toggle } blink_timer = 1; - blink_counter = ((!sysCfg.blinkcount) ? 64000 : (sysCfg.blinkcount *2)) +1; + blink_counter = ((!Settings.blinkcount) ? 64000 : (Settings.blinkcount *2)) +1; blink_mask |= mask; // Set device mask - mqtt_publishPowerBlinkState(device); + MqttPublishPowerBlinkState(device); return; } else if (4 == state) { // No Blink byte flag = (blink_mask & mask); - blink_mask &= (0xFF ^ mask); // Clear device mask - mqtt_publishPowerBlinkState(device); + blink_mask &= (POWER_MASK ^ mask); // Clear device mask + MqttPublishPowerBlinkState(device); if (flag) { - do_cmnd_power(device, (blink_powersave >> (device -1))&1); // Restore state + ExecuteCommandPower(device, (blink_powersave >> (device -1))&1); // Restore state } return; } - if (publishPower) { - mqtt_publishPowerState(device); + if (publish_power) { + MqttPublishPowerState(device); } } -void stop_all_power_blink() +void StopAllPowerBlink() { - byte mask; + power_t mask; - for (byte i = 1; i <= Maxdevice; i++) { - mask = 0x01 << (i -1); + for (byte i = 1; i <= devices_present; i++) { + mask = 1 << (i -1); if (blink_mask & mask) { - blink_mask &= (0xFF ^ mask); // Clear device mask - mqtt_publishPowerBlinkState(i); - do_cmnd_power(i, (blink_powersave >> (i -1))&1); // Restore state + blink_mask &= (POWER_MASK ^ mask); // Clear device mask + MqttPublishPowerBlinkState(i); + ExecuteCommandPower(i, (blink_powersave >> (i -1))&1); // Restore state } } } -void do_cmnd(char *cmnd) +void ExecuteCommand(char *cmnd) { char stopic[CMDSZ]; char svalue[INPUT_BUFFER_SIZE]; @@ -1732,20 +1673,21 @@ void do_cmnd(char *cmnd) } snprintf_P(stopic, sizeof(stopic), PSTR("/%s"), (token == NULL) ? "" : token); token = strtok(NULL, ""); - snprintf_P(svalue, sizeof(svalue), (token == NULL) ? "" : token); - mqttDataCb(stopic, (byte*)svalue, strlen(svalue)); +// snprintf_P(svalue, sizeof(svalue), (token == NULL) ? "" : token); // Fails with command FullTopic home/%prefix%/%topic% as it processes %p of %prefix% + strlcpy(svalue, (token == NULL) ? "" : token, sizeof(svalue)); // Fixed 5.8.0b + MqttDataCallback(stopic, (byte*)svalue, strlen(svalue)); } -void publish_status(uint8_t payload) +void PublishStatus(uint8_t payload) { uint8_t option = 1; // Workaround MQTT - TCP/IP stack queueing when SUB_PREFIX = PUB_PREFIX - if (!strcmp(sysCfg.mqtt_prefix[0],sysCfg.mqtt_prefix[1]) && (!payload)) { + if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1]) && (!payload)) { option++; } - if ((!sysCfg.flag.mqtt_enabled) && (6 == payload)) { + if ((!Settings.flag.mqtt_enabled) && (6 == payload)) { payload = 99; } if ((!hlw_flg) && ((8 == payload) || (9 == payload))) { @@ -1754,157 +1696,160 @@ void publish_status(uint8_t payload) if ((0 == payload) || (99 == payload)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS "\":{\"" D_CMND_MODULE "\":%d, \"" D_CMND_FRIENDLYNAME "\":\"%s\", \"" D_CMND_TOPIC "\":\"%s\", \"" D_CMND_BUTTONTOPIC "\":\"%s\", \"" D_CMND_POWER "\":%d, \"" D_CMND_POWERONSTATE "\":%d, \"" D_CMND_LEDSTATE "\":%d, \"" D_CMND_SAVEDATA "\":%d, \"" D_SAVESTATE "\":%d, \"" D_CMND_BUTTONRETAIN "\":%d, \"" D_CMND_POWERRETAIN "\":%d}}"), - sysCfg.module +1, sysCfg.friendlyname[0], sysCfg.mqtt_topic, sysCfg.button_topic, power, sysCfg.poweronstate, sysCfg.ledstate, sysCfg.savedata, sysCfg.flag.savestate, sysCfg.flag.mqtt_button_retain, sysCfg.flag.mqtt_power_retain); - mqtt_publish_topic_P(option, PSTR(D_CMND_STATUS)); + Settings.module +1, Settings.friendlyname[0], Settings.mqtt_topic, Settings.button_topic, power, Settings.poweronstate, Settings.ledstate, Settings.save_data, Settings.flag.save_state, Settings.flag.mqtt_button_retain, Settings.flag.mqtt_power_retain); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS)); } if ((0 == payload) || (1 == payload)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_BAUDRATE "\":%d, \"" D_CMND_GROUPTOPIC "\":\"%s\", \"" D_CMND_OTAURL "\":\"%s\", \"" D_UPTIME "\":%d, \"" D_CMND_SLEEP "\":%d, \"" D_BOOTCOUNT "\":%d, \"" D_SAVECOUNT "\":%d, \"" D_SAVEADDRESS "\":\"%X\"}}"), - Baudrate, sysCfg.mqtt_grptopic, sysCfg.otaUrl, uptime, sysCfg.sleep, sysCfg.bootcount, sysCfg.saveFlag, CFG_Address()); - mqtt_publish_topic_P(option, PSTR(D_CMND_STATUS "1")); + baudrate, Settings.mqtt_grptopic, Settings.ota_url, uptime, Settings.sleep, Settings.bootcount, Settings.save_flag, GetSettingsAddress()); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1")); } if ((0 == payload) || (2 == payload)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_VERSION "\":\"%s\", \"" D_BUILDDATETIME "\":\"%s\", \"" D_BOOTVERSION "\":%d, \"" D_COREVERSION "\":\"%s\", \"" D_SDKVERSION "\":\"%s\"}}"), - Version, getBuildDateTime().c_str(), ESP.getBootVersion(), ESP.getCoreVersion().c_str(), ESP.getSdkVersion()); - mqtt_publish_topic_P(option, PSTR(D_CMND_STATUS "2")); + version, GetBuildDateAndTime().c_str(), ESP.getBootVersion(), ESP.getCoreVersion().c_str(), ESP.getSdkVersion()); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "2")); } if ((0 == payload) || (3 == payload)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d, \"" D_CMND_WEBLOG "\":%d, \"" D_CMND_SYSLOG "\":%d, \"" D_CMND_LOGHOST "\":\"%s\", \"" D_CMND_LOGPORT "\":%d, \"" D_CMND_SSID "1\":\"%s\", \"" D_CMND_SSID "2\":\"%s\", \"" D_CMND_TELEPERIOD "\":%d, \"" D_CMND_SETOPTION "\":\"%08X\"}}"), - sysCfg.seriallog_level, sysCfg.weblog_level, sysCfg.syslog_level, sysCfg.syslog_host, sysCfg.syslog_port, sysCfg.sta_ssid[0], sysCfg.sta_ssid[1], sysCfg.tele_period, sysCfg.flag.data); - mqtt_publish_topic_P(option, PSTR(D_CMND_STATUS "3")); + Settings.seriallog_level, Settings.weblog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.sta_ssid[0], Settings.sta_ssid[1], Settings.tele_period, Settings.flag.data); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "3")); } if ((0 == payload) || (4 == payload)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_PROGRAMSIZE "\":%d, \"" D_FREEMEMORY "\":%d, \"" D_HEAPSIZE "\":%d, \"" D_PROGRAMFLASHSIZE "\":%d, \"" D_FLASHSIZE "\":%d, \"" D_FLASHMODE "\":%d}}"), ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipMode()); - mqtt_publish_topic_P(option, PSTR(D_CMND_STATUS "4")); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "4")); } if ((0 == payload) || (5 == payload)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS5_NETWORK "\":{\"" D_CMND_HOSTNAME "\":\"%s\", \"" D_CMND_IPADDRESS "\":\"%s\", \"" D_GATEWAY "\":\"%s\", \"" D_SUBNETMASK "\":\"%s\", \"" D_DNSSERVER "\":\"%s\", \"" D_MAC "\":\"%s\", \"" D_CMND_WEBSERVER "\":%d, \"" D_CMND_WIFICONFIG "\":%d}}"), - Hostname, WiFi.localIP().toString().c_str(), IPAddress(sysCfg.ip_address[1]).toString().c_str(), IPAddress(sysCfg.ip_address[2]).toString().c_str(), IPAddress(sysCfg.ip_address[3]).toString().c_str(), - WiFi.macAddress().c_str(), sysCfg.webserver, sysCfg.sta_config); - mqtt_publish_topic_P(option, PSTR(D_CMND_STATUS "5")); + my_hostname, WiFi.localIP().toString().c_str(), IPAddress(Settings.ip_address[1]).toString().c_str(), IPAddress(Settings.ip_address[2]).toString().c_str(), IPAddress(Settings.ip_address[3]).toString().c_str(), + WiFi.macAddress().c_str(), Settings.webserver, Settings.sta_config); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "5")); } - if (((0 == payload) || (6 == payload)) && sysCfg.flag.mqtt_enabled) { + if (((0 == payload) || (6 == payload)) && Settings.flag.mqtt_enabled) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s\", \"" D_CMND_MQTTPORT "\":%d, \"" D_CMND_MQTTCLIENT D_MASK "\":\"%s\", \"" D_CMND_MQTTCLIENT "\":\"%s\", \"" D_CMND_MQTTUSER "\":\"%s\", \"MAX_PACKET_SIZE\":%d, \"KEEPALIVE\":%d}}"), - sysCfg.mqtt_host, sysCfg.mqtt_port, sysCfg.mqtt_client, MQTTClient, sysCfg.mqtt_user, MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); - mqtt_publish_topic_P(option, PSTR(D_CMND_STATUS "6")); + Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, mqtt_client, Settings.mqtt_user, MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "6")); } if ((0 == payload) || (7 == payload)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_UTC_TIME "\":\"%s\", \"" D_LOCAL_TIME "\":\"%s\", \"" D_STARTDST "\":\"%s\", \"" D_ENDDST "\":\"%s\", \"" D_CMND_TIMEZONE "\":%d}}"), - rtc_time(0).c_str(), rtc_time(1).c_str(), rtc_time(2).c_str(), rtc_time(3).c_str(), sysCfg.timezone); - mqtt_publish_topic_P(option, PSTR(D_CMND_STATUS "7")); + GetTime(0).c_str(), GetTime(1).c_str(), GetTime(2).c_str(), GetTime(3).c_str(), Settings.timezone); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "7")); } if (hlw_flg) { if ((0 == payload) || (8 == payload)) { - hlw_mqttStatus(); - mqtt_publish_topic_P(option, PSTR(D_CMND_STATUS "8")); + HlwMqttStatus(); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "8")); } if ((0 == payload) || (9 == payload)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS9_MARGIN "\":{\"" D_CMND_POWERLOW "\":%d, \"" D_CMND_POWERHIGH "\":%d, \"" D_CMND_VOLTAGELOW "\":%d, \"" D_CMND_VOLTAGEHIGH "\":%d, \"" D_CMND_CURRENTLOW "\":%d, \"" D_CMND_CURRENTHIGH "\":%d}}"), - sysCfg.hlw_pmin, sysCfg.hlw_pmax, sysCfg.hlw_umin, sysCfg.hlw_umax, sysCfg.hlw_imin, sysCfg.hlw_imax); - mqtt_publish_topic_P(option, PSTR(D_CMND_STATUS "9")); + Settings.hlw_pmin, Settings.hlw_pmax, Settings.hlw_umin, Settings.hlw_umax, Settings.hlw_imin, Settings.hlw_imax); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "9")); } } if ((0 == payload) || (10 == payload)) { uint8_t djson = 0; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS10_SENSOR "\":")); - sensors_mqttPresent(&djson); + MqttShowSensor(&djson); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); - mqtt_publish_topic_P(option, PSTR(D_CMND_STATUS "10")); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "10")); } if ((0 == payload) || (11 == payload)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS11_STATUS "\":")); - state_mqttPresent(); + MqttShowState(); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); - mqtt_publish_topic_P(option, PSTR(D_CMND_STATUS "11")); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "11")); } } -void state_mqttPresent() +void MqttShowState() { char stemp1[16]; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_TIME "\":\"%s\", \"" D_UPTIME "\":%d"), mqtt_data, getDateTime().c_str(), uptime); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_TIME "\":\"%s\", \"" D_UPTIME "\":%d"), mqtt_data, GetDateAndTime().c_str(), uptime); #ifdef USE_ADC_VCC dtostrfd((double)ESP.getVcc()/1000, 3, stemp1); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_VCC "\":%s"), mqtt_data, stemp1); #endif - for (byte i = 0; i < Maxdevice; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":\"%s\""), mqtt_data, getPowerDevice(stemp1, i +1, sizeof(stemp1)), getStateText(bitRead(power, i))); + for (byte i = 0; i < devices_present; i++) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":\"%s\""), mqtt_data, GetPowerDevice(stemp1, i +1, sizeof(stemp1)), GetStateText(bitRead(power, i))); } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_WIFI "\":{\"" D_AP "\":%d, \"" D_SSID "\":\"%s\", \"" D_RSSI "\":%d, \"" D_APMAC_ADDRESS "\":\"%s\"}}"), - mqtt_data, sysCfg.sta_active +1, sysCfg.sta_ssid[sysCfg.sta_active], WIFI_getRSSIasQuality(WiFi.RSSI()), WiFi.BSSIDstr().c_str()); + mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.BSSIDstr().c_str()); } -void sensors_mqttPresent(uint8_t* djson) +void MqttShowSensor(uint8_t* djson) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_TIME "\":\"%s\""), mqtt_data, getDateTime().c_str()); - for (byte i = 0; i < 4; i++) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_TIME "\":\"%s\""), mqtt_data, GetDateAndTime().c_str()); + for (byte i = 0; i < MAX_SWITCHES; i++) { if (pin[GPIO_SWT1 +i] < 99) { - boolean swm = ((FOLLOW_INV == sysCfg.switchmode[i]) || (PUSHBUTTON_INV == sysCfg.switchmode[i]) || (PUSHBUTTONHOLD_INV == sysCfg.switchmode[i])); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_SWITCH "%d\":\"%s\""), mqtt_data, i +1, getStateText(swm ^ lastwallswitch[i])); + boolean swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_SWITCH "%d\":\"%s\""), mqtt_data, i +1, GetStateText(swm ^ lastwallswitch[i])); *djson = 1; } } - counter_mqttPresent(djson); + MqttShowCounter(djson); #ifndef USE_ADC_VCC if (pin[GPIO_ADC0] < 99) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_ANALOG_INPUT0 "\":%d"), mqtt_data, getAdc0()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_ANALOG_INPUT0 "\":%d"), mqtt_data, GetAdc0()); *djson = 1; } #endif - if (SONOFF_SC == sysCfg.module) { - sc_mqttPresent(djson); + if (SONOFF_SC == Settings.module) { + MqttShowSonoffSC(djson); } if (pin[GPIO_DSB] < 99) { #ifdef USE_DS18B20 - dsb_mqttPresent(djson); + MqttShowDs18b20(djson); #endif // USE_DS18B20 #ifdef USE_DS18x20 - ds18x20_mqttPresent(djson); + MqttShowDs18x20(djson); #endif // USE_DS18x20 } #ifdef USE_DHT if (dht_flg) { - dht_mqttPresent(djson); + MqttShowDht(djson); } #endif // USE_DHT #ifdef USE_I2C if (i2c_flg) { #ifdef USE_SHT - sht_mqttPresent(djson); + MqttShowSht(djson); #endif // USE_SHT #ifdef USE_HTU - htu_mqttPresent(djson); + MqttShowHtu(djson); #endif // USE_HTU #ifdef USE_BMP - bmp_mqttPresent(djson); + MqttShowBmp(djson); #endif // USE_BMP #ifdef USE_BH1750 - bh1750_mqttPresent(djson); + MqttShowBh1750(djson); #endif // USE_BH1750 - } +#ifdef USE_VEML6070 + MqttShowVeml6070(djson); +#endif // USE_VEML6070 +} #endif // USE_I2C if (strstr_P(mqtt_data, PSTR(D_TEMPERATURE))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_TEMPERATURE_UNIT "\":\"%c\""), mqtt_data, tempUnit()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_TEMPERATURE_UNIT "\":\"%c\""), mqtt_data, TempUnit()); } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } /********************************************************************************************/ -void every_second() +void PerformEverySecond() { if (blockgpio0) { blockgpio0--; @@ -1920,7 +1865,7 @@ void every_second() seriallog_timer--; if (!seriallog_timer) { if (seriallog_level) { - addLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SERIAL_LOGGING_DISABLED)); + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SERIAL_LOGGING_DISABLED)); } seriallog_level = 0; } @@ -1929,92 +1874,95 @@ void every_second() if (syslog_timer) { // Restore syslog level syslog_timer--; if (!syslog_timer) { - syslog_level = (sysCfg.flag.emulation) ? 0 : sysCfg.syslog_level; - if (sysCfg.syslog_level) { - addLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_LOGGING_REENABLED)); // Might trigger disable again (on purpose) + syslog_level = (Settings.flag.emulation) ? 0 : Settings.syslog_level; + if (Settings.syslog_level) { + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_LOGGING_REENABLED)); // Might trigger disable again (on purpose) } } } #ifdef USE_DOMOTICZ - domoticz_mqttUpdate(); + DomoticzMqttUpdate(); #endif // USE_DOMOTICZ if (status_update_timer) { status_update_timer--; if (!status_update_timer) { - for (byte i = 1; i <= Maxdevice; i++) { - mqtt_publishPowerState(i); + for (byte i = 1; i <= devices_present; i++) { + MqttPublishPowerState(i); } } } - if (sysCfg.tele_period) { + if (Settings.tele_period) { tele_period++; - if (tele_period == sysCfg.tele_period -1) { + if (tele_period == Settings.tele_period -1) { if (pin[GPIO_DSB] < 99) { #ifdef USE_DS18B20 - dsb_readTempPrep(); + Ds18b20ReadTempPrep(); #endif // USE_DS18B20 #ifdef USE_DS18x20 - ds18x20_search(); // Check for changes in sensors number - ds18x20_convert(); // Start Conversion, takes up to one second + Ds18x20Search(); // Check for changes in sensors number + Ds18x20Convert(); // Start Conversion, takes up to one second #endif // USE_DS18x20 } #ifdef USE_DHT if (dht_flg) { - dht_readPrep(); + DhtReadPrep(); } #endif // USE_DHT #ifdef USE_I2C if (i2c_flg) { #ifdef USE_SHT - sht_detect(); + ShtDetect(); #endif // USE_SHT #ifdef USE_HTU - htu_detect(); + HtuDetect(); #endif // USE_HTU #ifdef USE_BMP - bmp_detect(); + BmpDetect(); #endif // USE_BMP #ifdef USE_BH1750 - bh1750_detect(); + Bh1750Detect(); #endif // USE_BH1750 - } +#ifdef USE_VEML6070 + Veml6070Detect(); +#endif // USE_VEML6070 +} #endif // USE_I2C } - if (tele_period >= sysCfg.tele_period) { + if (tele_period >= Settings.tele_period) { tele_period = 0; mqtt_data[0] = '\0'; - state_mqttPresent(); - mqtt_publish_topic_P(2, PSTR(D_RSLT_STATE)); + MqttShowState(); + MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_STATE)); uint8_t djson = 0; mqtt_data[0] = '\0'; - sensors_mqttPresent(&djson); + MqttShowSensor(&djson); if (djson) { - mqtt_publish_topic_P(2, PSTR(D_RSLT_SENSOR), sysCfg.flag.mqtt_sensor_retain); + MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); } if (hlw_flg) { - hlw_mqttPresent(1); + MqttShowHlw8012(1); } } } if (hlw_flg) { - hlw_margin_chk(); + HlwMarginCheck(); } - if ((2 == rtcTime.Minute) && uptime_flg) { - uptime_flg = false; + if ((2 == RtcTime.minute) && latest_uptime_flag) { + latest_uptime_flag = false; uptime++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_TIME "\":\"%s\", \"" D_UPTIME "\":%d}"), getDateTime().c_str(), uptime); - mqtt_publish_topic_P(2, PSTR(D_RSLT_UPTIME)); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_TIME "\":\"%s\", \"" D_UPTIME "\":%d}"), GetDateAndTime().c_str(), uptime); + MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_UPTIME)); } - if ((3 == rtcTime.Minute) && !uptime_flg) { - uptime_flg = true; + if ((3 == RtcTime.minute) && !latest_uptime_flag) { + latest_uptime_flag = true; } } @@ -2022,71 +1970,71 @@ void every_second() * Button handler with single press only or multi-press and hold on all buttons \*********************************************************************************************/ -void button_handler() +void ButtonHandler() { uint8_t button = NOT_PRESSED; - uint8_t butt_present = 0; - uint8_t flag = 0; + uint8_t button_present = 0; char scmnd[20]; - for (byte i = 0; i < Maxdevice; i++) { + uint8_t maxdev = (devices_present > MAX_KEYS) ? MAX_KEYS : devices_present; + for (byte i = 0; i < maxdev; i++) { button = NOT_PRESSED; - butt_present = 0; + button_present = 0; - if (!i && ((SONOFF_DUAL == sysCfg.module) || (CH4 == sysCfg.module))) { - butt_present = 1; - if (ButtonCode) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X"), ButtonCode); - addLog(LOG_LEVEL_DEBUG); + if (!i && ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module))) { + button_present = 1; + if (dual_button_code) { + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X"), dual_button_code); + AddLog(LOG_LEVEL_DEBUG); button = PRESSED; - if (0xF500 == ButtonCode) { // Button hold - holdbutton[i] = (sysCfg.param[P_HOLD_TIME] * (STATES / 10)) -1; + if (0xF500 == dual_button_code) { // Button hold + holdbutton[i] = (Settings.param[P_HOLD_TIME] * (STATES / 10)) -1; } - ButtonCode = 0; + dual_button_code = 0; } } else { if ((pin[GPIO_KEY1 +i] < 99) && !blockgpio0) { - butt_present = 1; + button_present = 1; button = digitalRead(pin[GPIO_KEY1 +i]); } } - if (butt_present) { - if (SONOFF_4CHPRO == sysCfg.module) { + if (button_present) { + if (SONOFF_4CHPRO == Settings.module) { if (holdbutton[i]) { holdbutton[i]--; } - flag = 0; + boolean button_pressed = false; if ((PRESSED == button) && (NOT_PRESSED == lastbutton[i])) { snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON " %d " D_LEVEL_10), i +1); - addLog(LOG_LEVEL_DEBUG); + AddLog(LOG_LEVEL_DEBUG); holdbutton[i] = STATES; - flag = 1; + button_pressed = true; } if ((NOT_PRESSED == button) && (PRESSED == lastbutton[i])) { snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON " %d " D_LEVEL_01), i +1); - addLog(LOG_LEVEL_DEBUG); + AddLog(LOG_LEVEL_DEBUG); if (!holdbutton[i]) { // Do not allow within 1 second - flag = 1; + button_pressed = true; } } - if (flag) { + if (button_pressed) { if (!send_button_power(0, i +1, 2)) { // Execute Toggle command via MQTT if ButtonTopic is set - do_cmnd_power(i +1, 2); // Execute Toggle command internally + ExecuteCommandPower(i +1, 2); // Execute Toggle command internally } } } else { if ((PRESSED == button) && (NOT_PRESSED == lastbutton[i])) { - if (sysCfg.flag.button_single) { // Allow only single button press for immediate action + if (Settings.flag.button_single) { // Allow only single button press for immediate action snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON " %d " D_IMMEDIATE), i +1); - addLog(LOG_LEVEL_DEBUG); + AddLog(LOG_LEVEL_DEBUG); if (!send_button_power(0, i +1, 2)) { // Execute Toggle command via MQTT if ButtonTopic is set - do_cmnd_power(i +1, 2); // Execute Toggle command internally + ExecuteCommandPower(i +1, 2); // Execute Toggle command internally } } else { multipress[i] = (multiwindow[i]) ? multipress[i] +1 : 1; snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON " %d " D_MULTI_PRESS " %d"), i +1, multipress[i]); - addLog(LOG_LEVEL_DEBUG); + AddLog(LOG_LEVEL_DEBUG); multiwindow[i] = STATES /2; // 0.5 second multi press window } blinks = 201; @@ -2096,18 +2044,18 @@ void button_handler() holdbutton[i] = 0; } else { holdbutton[i]++; - if (sysCfg.flag.button_single) { // Allow only single button press for immediate action - if (holdbutton[i] == sysCfg.param[P_HOLD_TIME] * (STATES / 10) * 4) { // Button hold for four times longer -// sysCfg.flag.button_single = 0; + if (Settings.flag.button_single) { // Allow only single button press for immediate action + if (holdbutton[i] == Settings.param[P_HOLD_TIME] * (STATES / 10) * 4) { // Button hold for four times longer +// Settings.flag.button_single = 0; snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_SETOPTION "13 0")); // Disable single press only - do_cmnd(scmnd); + ExecuteCommand(scmnd); } } else { - if (holdbutton[i] == sysCfg.param[P_HOLD_TIME] * (STATES / 10)) { // Button hold + if (holdbutton[i] == Settings.param[P_HOLD_TIME] * (STATES / 10)) { // Button hold multipress[i] = 0; - if (!sysCfg.flag.button_restrict) { // No button restriction + if (!Settings.flag.button_restrict) { // No button restriction snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); - do_cmnd(scmnd); + ExecuteCommand(scmnd); } else { send_button_power(0, i +1, 3); // Execute Hold command via MQTT if ButtonTopic is set } @@ -2115,33 +2063,33 @@ void button_handler() } } - if (!sysCfg.flag.button_single) { // Allow multi-press + if (!Settings.flag.button_single) { // Allow multi-press if (multiwindow[i]) { multiwindow[i]--; } else { - if (!restartflag && !holdbutton[i] && (multipress[i] > 0) && (multipress[i] < MAX_BUTTON_COMMANDS +3)) { - flag = 0; + if (!restart_flag && !holdbutton[i] && (multipress[i] > 0) && (multipress[i] < MAX_BUTTON_COMMANDS +3)) { + boolean single_press = false; if (multipress[i] < 3) { // Single or Double press - if ((SONOFF_DUAL == sysCfg.module) || (CH4 == sysCfg.module)) { - flag = 1; + if ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) { + single_press = true; } else { - flag = (sysCfg.flag.button_swap +1 == multipress[i]); + single_press = (Settings.flag.button_swap +1 == multipress[i]); multipress[i] = 1; } } - if (flag && send_button_power(0, i + multipress[i], 2)) { // Execute Toggle command via MQTT if ButtonTopic is set + if (single_press && send_button_power(0, i + multipress[i], 2)) { // Execute Toggle command via MQTT if ButtonTopic is set // Success } else { if (multipress[i] < 3) { // Single or Double press - if (WIFI_State()) { // WPSconfig, Smartconfig or Wifimanager active - restartflag = 1; + if (WifiState()) { // WPSconfig, Smartconfig or Wifimanager active + restart_flag = 1; } else { - do_cmnd_power(i + multipress[i], 2); // Execute Toggle command internally + ExecuteCommandPower(i + multipress[i], 2); // Execute Toggle command internally } } else { // 3 - 7 press - if (!sysCfg.flag.button_restrict) { - snprintf_P(scmnd, sizeof(scmnd), commands[multipress[i] -3]); - do_cmnd(scmnd); + if (!Settings.flag.button_restrict) { + snprintf_P(scmnd, sizeof(scmnd), kCommands[multipress[i] -3]); + ExecuteCommand(scmnd); } } } @@ -2159,12 +2107,12 @@ void button_handler() * Switch handler \*********************************************************************************************/ -void switch_handler() +void SwitchHandler() { uint8_t button = NOT_PRESSED; uint8_t switchflag; - for (byte i = 0; i < 4; i++) { + for (byte i = 0; i < MAX_SWITCHES; i++) { if (pin[GPIO_SWT1 +i] < 99) { if (holdwallswitch[i]) { @@ -2177,15 +2125,15 @@ void switch_handler() button = digitalRead(pin[GPIO_SWT1 +i]); if (button != lastwallswitch[i]) { switchflag = 3; - switch (sysCfg.switchmode[i]) { + switch (Settings.switchmode[i]) { case TOGGLE: - switchflag = 2; // Toggle + switchflag = 2; // Toggle break; case FOLLOW: - switchflag = button & 0x01; // Follow wall switch state + switchflag = button &1; // Follow wall switch state break; case FOLLOW_INV: - switchflag = ~button & 0x01; // Follow inverted wall switch state + switchflag = ~button &1; // Follow inverted wall switch state break; case PUSHBUTTON: if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i])) { @@ -2199,7 +2147,7 @@ void switch_handler() break; case PUSHBUTTONHOLD: if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i])) { - holdwallswitch[i] = sysCfg.param[P_HOLD_TIME] * (STATES / 10); + holdwallswitch[i] = Settings.param[P_HOLD_TIME] * (STATES / 10); } if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i]) && (holdwallswitch[i])) { holdwallswitch[i] = 0; @@ -2208,7 +2156,7 @@ void switch_handler() break; case PUSHBUTTONHOLD_INV: if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i])) { - holdwallswitch[i] = sysCfg.param[P_HOLD_TIME] * (STATES / 10); + holdwallswitch[i] = Settings.param[P_HOLD_TIME] * (STATES / 10); } if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i]) && (holdwallswitch[i])) { holdwallswitch[i] = 0; @@ -2219,7 +2167,7 @@ void switch_handler() if (switchflag < 3) { if (!send_button_power(1, i +1, switchflag)) { // Execute command via MQTT - do_cmnd_power(i +1, switchflag); // Execute command internally (if i < Maxdevice) + ExecuteCommandPower(i +1, switchflag); // Execute command internally (if i < devices_present) } } @@ -2233,11 +2181,11 @@ void switch_handler() * State loop \*********************************************************************************************/ -void stateloop() +void StateLoop() { - uint8_t power_now; + power_t power_now; - timerxs = millis() + (1000 / STATES); + state_loop_timer = millis() + (1000 / STATES); state++; /*-------------------------------------------------------------------------------------------*\ @@ -2246,7 +2194,7 @@ void stateloop() if (STATES == state) { state = 0; - every_second(); + PerformEverySecond(); } /*-------------------------------------------------------------------------------------------*\ @@ -2262,7 +2210,7 @@ void stateloop() if (latching_relay_pulse) { latching_relay_pulse--; if (!latching_relay_pulse) { - setLatchingRelay(0, 0); + SetLatchingRelay(0, 0); } } @@ -2270,7 +2218,7 @@ void stateloop() if ((pulse_timer[i] > 0) && (pulse_timer[i] < 112)) { pulse_timer[i]--; if (!pulse_timer[i]) { - do_cmnd_power(i +1, 0); + ExecuteCommandPower(i +1, 0); } } } @@ -2278,45 +2226,53 @@ void stateloop() if (blink_mask) { blink_timer--; if (!blink_timer) { - blink_timer = sysCfg.blinktime; + blink_timer = Settings.blinktime; blink_counter--; if (!blink_counter) { - stop_all_power_blink(); + StopAllPowerBlink(); } else { blink_power ^= 1; - power_now = (power & (0xFF ^ blink_mask)) | ((blink_power) ? blink_mask : 0); - setRelay(power_now); + power_now = (power & (POWER_MASK ^ blink_mask)) | ((blink_power) ? blink_mask : 0); + SetDevicePower(power_now); } } } // Backlog - if (blogdelay) { - blogdelay--; + if (backlog_delay) { + backlog_delay--; } - if ((blogptr != blogidx) && !blogdelay && !blogmutex) { - blogmutex = 1; - do_cmnd((char*)Backlog[blogptr].c_str()); - blogmutex = 0; - blogptr++; + if ((backlog_pointer != backlog_index) && !backlog_delay && !backlog_mutex) { + backlog_mutex = 1; + ExecuteCommand((char*)backlog[backlog_pointer].c_str()); + backlog_mutex = 0; + backlog_pointer++; /* - if (blogptr >= MAX_BACKLOG) { - blogptr = 0; + if (backlog_pointer >= MAX_BACKLOG) { + backlog_pointer = 0; } */ - blogptr &= 0xF; + backlog_pointer &= 0xF; } } +#ifdef USE_IR_REMOTE +#ifdef USE_IR_RECEIVE + if (pin[GPIO_IRRECV] < 99) { + IrReceiveCheck(); // check if there's anything on IR side + } +#endif // USE_IR_RECEIVE +#endif // USE_IR_REMOTE + /*-------------------------------------------------------------------------------------------*\ * Every 0.05 second \*-------------------------------------------------------------------------------------------*/ - button_handler(); - switch_handler(); + ButtonHandler(); + SwitchHandler(); - if (sfl_flg) { // Sonoff B1, AiLight, Sonoff led or BN-SZ01 - sl_animate(); + if (light_type) { + LightAnimate(); } /*-------------------------------------------------------------------------------------------*\ @@ -2324,14 +2280,14 @@ void stateloop() \*-------------------------------------------------------------------------------------------*/ if (!(state % ((STATES/10)*2))) { - if (blinks || restartflag || otaflag) { - if (restartflag || otaflag) { + if (blinks || restart_flag || ota_state_flag) { + if (restart_flag || ota_state_flag) { blinkstate = 1; // Stay lit } else { blinkstate ^= 1; // Blink } - if ((!(sysCfg.ledstate &0x08)) && ((sysCfg.ledstate &0x06) || (blinks > 200) || (blinkstate))) { - setLed(blinkstate); + if ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (blinks > 200) || (blinkstate))) { + SetLedPower(blinkstate); } if (!blinkstate) { blinks--; @@ -2340,12 +2296,12 @@ void stateloop() } } } else { - if (sysCfg.ledstate &0x01) { + if (Settings.ledstate &1) { boolean tstate = power; - if ((SONOFF_TOUCH == sysCfg.module) || (SONOFF_T11 == sysCfg.module) || (SONOFF_T12 == sysCfg.module) || (SONOFF_T13 == sysCfg.module)) { + if ((SONOFF_TOUCH == Settings.module) || (SONOFF_T11 == Settings.module) || (SONOFF_T12 == Settings.module) || (SONOFF_T13 == Settings.module)) { tstate = (!power) ? 1 : 0; } - setLed(tstate); + SetLedPower(tstate); } } } @@ -2356,108 +2312,112 @@ void stateloop() switch (state) { case (STATES/10)*2: - if (otaflag && (blogptr == blogidx)) { - otaflag--; - if (2 == otaflag) { - otaretry = OTA_ATTEMPTS; + if (ota_state_flag && (backlog_pointer == backlog_index)) { + ota_state_flag--; + if (2 == ota_state_flag) { + ota_retry_counter = OTA_ATTEMPTS; ESPhttpUpdate.rebootOnUpdate(false); - CFG_Save(1); // Free flash for OTA update + SettingsSave(1); // Free flash for OTA update } - if (otaflag <= 0) { + if (ota_state_flag <= 0) { #ifdef USE_WEBSERVER - if (sysCfg.webserver) { - stopWebserver(); + if (Settings.webserver) { + StopWebserver(); } #endif // USE_WEBSERVER - otaflag = 92; - otaok = 0; - otaretry--; - if (otaretry) { -// snprintf_P(log_data, sizeof(log_data), PSTR("OTA: Attempt %d"), OTA_ATTEMPTS - otaretry); -// addLog(LOG_LEVEL_INFO); - otaok = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(sysCfg.otaUrl)); - if (!otaok) { - otaflag = 2; + ota_state_flag = 92; + ota_result = 0; + ota_retry_counter--; + if (ota_retry_counter) { +// snprintf_P(log_data, sizeof(log_data), PSTR("OTA: Attempt %d"), OTA_ATTEMPTS - ota_retry_counter); +// AddLog(LOG_LEVEL_INFO); + ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(Settings.ota_url)); + if (!ota_result) { + ota_state_flag = 2; } } } - if (90 == otaflag) { // Allow MQTT to reconnect - otaflag = 0; - if (otaok) { - setFlashModeDout(); // Force DOUT for both ESP8266 and ESP8285 + if (90 == ota_state_flag) { // Allow MQTT to reconnect + ota_state_flag = 0; + if (ota_result) { + SetFlashModeDout(); // Force DOUT for both ESP8266 and ESP8285 snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_SUCCESSFUL ". " D_RESTARTING)); } else { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); } - restartflag = 2; // Restart anyway to keep memory clean webserver - mqtt_publish_topic_P(1, PSTR(D_CMND_UPGRADE)); + restart_flag = 2; // Restart anyway to keep memory clean webserver + MqttPublishPrefixTopic_P(1, PSTR(D_CMND_UPGRADE)); } } break; case (STATES/10)*4: - if (rtc_midnight_now()) { - counter_savestate(); + if (MidnightNow()) { + CounterSaveState(); } - if (savedatacounter && (blogptr == blogidx)) { - savedatacounter--; - if (savedatacounter <= 0) { - if (sysCfg.flag.savestate) { - byte mask = 0xFF; + if (save_data_counter && (backlog_pointer == backlog_index)) { + save_data_counter--; + if (save_data_counter <= 0) { + if (Settings.flag.save_state) { + power_t mask = POWER_MASK; for (byte i = 0; i < MAX_PULSETIMERS; i++) { - if ((sysCfg.pulsetime[i] > 0) && (sysCfg.pulsetime[i] < 30)) { + if ((Settings.pulse_timer[i] > 0) && (Settings.pulse_timer[i] < 30)) { // 3 seconds mask &= ~(1 << i); } } - if (!((sysCfg.power &mask) == (power &mask))) { - sysCfg.power = power; + if (!((Settings.power &mask) == (power &mask))) { + Settings.power = power; } + } else { + Settings.power = 0; } - CFG_Save(0); - savedatacounter = sysCfg.savedata; + SettingsSave(0); + save_data_counter = Settings.save_data; } } - if (restartflag && (blogptr == blogidx)) { - if (211 == restartflag) { - CFG_Default(); - restartflag = 2; + if (restart_flag && (backlog_pointer == backlog_index)) { + if (211 == restart_flag) { + SettingsDefault(); + restart_flag = 2; } - if (212 == restartflag) { - CFG_Erase(); - CFG_Default(); - restartflag = 2; + if (212 == restart_flag) { + SettingsErase(); + SettingsDefault(); + restart_flag = 2; } - if (sysCfg.flag.savestate) { - sysCfg.power = power; + if (Settings.flag.save_state) { + Settings.power = power; + } else { + Settings.power = 0; } if (hlw_flg) { - hlw_savestate(); + HlwSaveState(); } - counter_savestate(); - CFG_Save(0); - restartflag--; - if (restartflag <= 0) { - addLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); + CounterSaveState(); + SettingsSave(0); + restart_flag--; + if (restart_flag <= 0) { + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); ESP.restart(); } } break; case (STATES/10)*6: - WIFI_Check(wificheckflag); - wificheckflag = WIFI_RESTART; + WifiCheck(wifi_state_flag); + wifi_state_flag = WIFI_RESTART; break; case (STATES/10)*8: if (WL_CONNECTED == WiFi.status()) { - if (sysCfg.flag.mqtt_enabled) { - if (!mqttClient.connected()) { - if (!mqttcounter) { - mqtt_reconnect(); + if (Settings.flag.mqtt_enabled) { + if (!MqttClient.connected()) { + if (!mqtt_retry_counter) { + MqttReconnect(); } else { - mqttcounter--; + mqtt_retry_counter--; } } } else { - if (!mqttcounter) { - mqtt_reconnect(); + if (!mqtt_retry_counter) { + MqttReconnect(); } } } @@ -2467,55 +2427,55 @@ void stateloop() /********************************************************************************************/ -void serial() +void SerialInput() { while (Serial.available()) { yield(); - SerialInByte = Serial.read(); + serial_in_byte = Serial.read(); /*-------------------------------------------------------------------------------------------*\ * Sonoff dual 19200 baud serial interface \*-------------------------------------------------------------------------------------------*/ - if (Hexcode) { - Hexcode--; - if (Hexcode) { - ButtonCode = (ButtonCode << 8) | SerialInByte; - SerialInByte = 0; + if (dual_hex_code) { + dual_hex_code--; + if (dual_hex_code) { + dual_button_code = (dual_button_code << 8) | serial_in_byte; + serial_in_byte = 0; } else { - if (SerialInByte != 0xA1) { - ButtonCode = 0; // 0xA1 - End of Sonoff dual button code + if (serial_in_byte != 0xA1) { + dual_button_code = 0; // 0xA1 - End of Sonoff dual button code } } } - if (0xA0 == SerialInByte) { // 0xA0 - Start of Sonoff dual button code - SerialInByte = 0; - ButtonCode = 0; - Hexcode = 3; + if (0xA0 == serial_in_byte) { // 0xA0 - Start of Sonoff dual button code + serial_in_byte = 0; + dual_button_code = 0; + dual_hex_code = 3; } /*-------------------------------------------------------------------------------------------*\ * Sonoff bridge 19200 baud serial interface \*-------------------------------------------------------------------------------------------*/ - if (sb_serial()) { - SerialInByteCounter = 0; + if (SonoffBridgeSerialInput()) { + serial_in_byte_counter = 0; Serial.flush(); return; } /*-------------------------------------------------------------------------------------------*/ - if (SerialInByte > 127) { // binary data... - SerialInByteCounter = 0; + if (serial_in_byte > 127) { // binary data... + serial_in_byte_counter = 0; Serial.flush(); return; } - if (isprint(SerialInByte)) { - if (SerialInByteCounter < INPUT_BUFFER_SIZE) { // add char to string if it still fits - serialInBuf[SerialInByteCounter++] = SerialInByte; + if (isprint(serial_in_byte)) { + if (serial_in_byte_counter < INPUT_BUFFER_SIZE) { // add char to string if it still fits + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; } else { - SerialInByteCounter = 0; + serial_in_byte_counter = 0; } } @@ -2523,23 +2483,23 @@ void serial() * Sonoff SC 19200 baud serial interface \*-------------------------------------------------------------------------------------------*/ - if (SerialInByte == '\x1B') { // Sonoff SC status from ATMEGA328P - serialInBuf[SerialInByteCounter] = 0; // serial data completed - sc_rcvstat(serialInBuf); - SerialInByteCounter = 0; + if (serial_in_byte == '\x1B') { // Sonoff SC status from ATMEGA328P + serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed + SonoffScSerialInput(serial_in_buffer); + serial_in_byte_counter = 0; Serial.flush(); return; } /*-------------------------------------------------------------------------------------------*/ - else if (SerialInByte == '\n') { - serialInBuf[SerialInByteCounter] = 0; // serial data completed - seriallog_level = (sysCfg.seriallog_level < LOG_LEVEL_INFO) ? LOG_LEVEL_INFO : sysCfg.seriallog_level; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_COMMAND "%s"), serialInBuf); - addLog(LOG_LEVEL_INFO); - do_cmnd(serialInBuf); - SerialInByteCounter = 0; + else if (serial_in_byte == '\n') { + serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed + seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? LOG_LEVEL_INFO : Settings.seriallog_level; + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_COMMAND "%s"), serial_in_buffer); + AddLog(LOG_LEVEL_INFO); + ExecuteCommand(serial_in_buffer); + serial_in_byte_counter = 0; Serial.flush(); return; } @@ -2548,21 +2508,20 @@ void serial() /********************************************************************************************/ -void GPIO_init() +void GpioInit() { uint8_t mpin; mytmplt def_module; - if (!sysCfg.module || (sysCfg.module >= MAXMODULE)) { - sysCfg.module = MODULE; + if (!Settings.module || (Settings.module >= MAXMODULE)) { + Settings.module = MODULE; } - memcpy_P(&def_module, &modules[sysCfg.module], sizeof(def_module)); -// sysCfg.my_module.flag = def_module.flag; + memcpy_P(&def_module, &kModules[Settings.module], sizeof(def_module)); strlcpy(my_module.name, def_module.name, sizeof(my_module.name)); for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if (sysCfg.my_module.gp.io[i] > GPIO_NONE) { - my_module.gp.io[i] = sysCfg.my_module.gp.io[i]; + if (Settings.my_gp.io[i] > GPIO_NONE) { + my_module.gp.io[i] = Settings.my_gp.io[i]; } if ((def_module.gp.io[i] > GPIO_NONE) && (def_module.gp.io[i] < GPIO_USER)) { my_module.gp.io[i] = def_module.gp.io[i]; @@ -2576,20 +2535,24 @@ void GPIO_init() mpin = my_module.gp.io[i]; // snprintf_P(log_data, sizeof(log_data), PSTR("DBG: gpio pin %d, mpin %d"), i, mpin); -// addLog(LOG_LEVEL_DEBUG); +// AddLog(LOG_LEVEL_DEBUG); if (mpin) { - if ((mpin >= GPIO_REL1_INV) && (mpin <= GPIO_REL4_INV)) { - rel_inverted[mpin - GPIO_REL1_INV] = 1; - mpin -= 4; + if ((mpin >= GPIO_REL1_INV) && (mpin < (GPIO_REL1_INV + MAX_RELAYS))) { + bitSet(rel_inverted, mpin - GPIO_REL1_INV); + mpin -= (GPIO_REL1_INV - GPIO_REL1); } - else if ((mpin >= GPIO_LED1_INV) && (mpin <= GPIO_LED4_INV)) { - led_inverted[mpin - GPIO_LED1_INV] = 1; - mpin -= 4; + else if ((mpin >= GPIO_LED1_INV) && (mpin < (GPIO_LED1_INV + MAX_LEDS))) { + bitSet(led_inverted, mpin - GPIO_LED1_INV); + mpin -= (GPIO_LED1_INV - GPIO_LED1); + } + else if ((mpin >= GPIO_PWM1_INV) && (mpin < (GPIO_PWM1_INV + MAX_PWMS))) { + bitSet(pwm_inverted, mpin - GPIO_PWM1_INV); + mpin -= (GPIO_PWM1_INV - GPIO_PWM1); } #ifdef USE_DHT else if ((mpin >= GPIO_DHT11) && (mpin <= GPIO_DHT22)) { - if (dht_setup(i, mpin)) { + if (DhtSetup(i, mpin)) { dht_flg = 1; mpin = GPIO_DHT11; } else { @@ -2607,113 +2570,8 @@ void GPIO_init() Serial.set_tx(2); } - analogWriteRange(PWM_RANGE); // Default is 1023 (Arduino.h) - analogWriteFreq(PWM_FREQ); // Default is 1000 (core_esp8266_wiring_pwm.c) - - Maxdevice = 1; - if (SONOFF_BRIDGE == sysCfg.module) { - Baudrate = 19200; - } - if (SONOFF_DUAL == sysCfg.module) { - Maxdevice = 2; - Baudrate = 19200; - } - else if (CH4 == sysCfg.module) { - Maxdevice = 4; - Baudrate = 19200; - } - else if (SONOFF_SC == sysCfg.module) { - Maxdevice = 0; - Baudrate = 19200; - } - else if (SONOFF_BN == sysCfg.module) { // Single color led (White) - sfl_flg = 1; - } - else if (SONOFF_LED == sysCfg.module) { // Dual color led (White warm and cold) - sfl_flg = 2; - } - else if (AILIGHT == sysCfg.module) { // RGBW led - sfl_flg = 4; - } - else if (SONOFF_B1 == sysCfg.module) { // RGBWC led - sfl_flg = 5; - } - else { - Maxdevice = 0; - for (byte i = 0; i < 4; i++) { - if (pin[GPIO_REL1 +i] < 99) { - pinMode(pin[GPIO_REL1 +i], OUTPUT); - Maxdevice++; - } -// if (pin[GPIO_KEY1 +i] < 99) { -// pinMode(pin[GPIO_KEY1 +i], (16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP); -// } - } - } - for (byte i = 0; i < 4; i++) { - if (pin[GPIO_KEY1 +i] < 99) { - pinMode(pin[GPIO_KEY1 +i], (16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP); - } - if (pin[GPIO_LED1 +i] < 99) { - pinMode(pin[GPIO_LED1 +i], OUTPUT); - digitalWrite(pin[GPIO_LED1 +i], led_inverted[i]); - } - if (pin[GPIO_SWT1 +i] < 99) { - pinMode(pin[GPIO_SWT1 +i], (16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 :INPUT_PULLUP); - lastwallswitch[i] = digitalRead(pin[GPIO_SWT1 +i]); // set global now so doesn't change the saved power state on first switch check - } - } - -#ifdef USE_WS2812 - if (!sfl_flg && (pin[GPIO_WS2812] < 99)) { - Maxdevice++; - sfl_flg = 3; - } -#endif // USE_WS2812 - if (sfl_flg) { // Sonoff B1, AiLight, Sonoff Led or BN-SZ01, WS2812 - if (sfl_flg < 3) { - pwm_idxoffset = sfl_flg; // 1 for BN-SZ01, 2 for Sonoff Led - } - sl_init(); - } - for (byte i = pwm_idxoffset; i < 5; i++) { - if (pin[GPIO_PWM1 +i] < 99) { - pwm_flg = 1; - pinMode(pin[GPIO_PWM1 +i], OUTPUT); - analogWrite(pin[GPIO_PWM1 +i], sysCfg.pwmvalue[i]); - } - } - - if (EXS_RELAY == sysCfg.module) { - setLatchingRelay(0,2); - setLatchingRelay(1,2); - } - setLed(sysCfg.ledstate &8); - -#ifdef USE_IR_REMOTE - if (pin[GPIO_IRSEND] < 99) { - ir_send_init(); - } -#endif // USE_IR_REMOTE - - counter_init(); - - hlw_flg = ((pin[GPIO_HLW_SEL] < 99) && (pin[GPIO_HLW_CF1] < 99) && (pin[GPIO_HLW_CF] < 99)); - if (hlw_flg) { - hlw_init(); - } - -#ifdef USE_DHT - if (dht_flg) { - dht_init(); - } -#endif // USE_DHT - -#ifdef USE_DS18x20 - if (pin[GPIO_DSB] < 99) { - ds18x20_init(); - } -#endif // USE_DS18x20 + analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h) + analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c) #ifdef USE_I2C i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99)); @@ -2721,6 +2579,129 @@ void GPIO_init() Wire.begin(pin[GPIO_I2C_SDA], pin[GPIO_I2C_SCL]); } #endif // USE_I2C + + devices_present = 1; + if (Settings.flag.pwm_control) { + light_type = LT_BASIC; + for (byte i = 0; i < MAX_PWMS; i++) { + if (pin[GPIO_PWM1 +i] < 99) { + light_type++; // Use Dimmer/Color control for all PWM as SetOption15 = 1 + } + } + } + if (SONOFF_BRIDGE == Settings.module) { + baudrate = 19200; + } + if (SONOFF_DUAL == Settings.module) { + devices_present = 2; + baudrate = 19200; + } + else if (CH4 == Settings.module) { + devices_present = 4; + baudrate = 19200; + } + else if (SONOFF_SC == Settings.module) { + devices_present = 0; + baudrate = 19200; + } + else if ((H801 == Settings.module) || (MAGICHOME == Settings.module) || (ARILUX == Settings.module)) { // PWM RGBCW led + if (!Settings.flag.pwm_control) { + light_type = LT_BASIC; // Use basic PWM control if SetOption15 = 0 + } + } + else if (SONOFF_BN == Settings.module) { // PWM Single color led (White) + light_type = LT_PWM1; + } + else if (SONOFF_LED == Settings.module) { // PWM Dual color led (White warm and cold) + light_type = LT_PWM2; + } + else if (AILIGHT == Settings.module) { // RGBW led + light_type = LT_RGBW; + } + else if (SONOFF_B1 == Settings.module) { // RGBWC led + light_type = LT_RGBWC; + } + else { + if (!light_type) { + devices_present = 0; + } + for (byte i = 0; i < MAX_RELAYS; i++) { + if (pin[GPIO_REL1 +i] < 99) { + pinMode(pin[GPIO_REL1 +i], OUTPUT); + devices_present++; + } + } + } + for (byte i = 0; i < MAX_KEYS; i++) { + if (pin[GPIO_KEY1 +i] < 99) { + pinMode(pin[GPIO_KEY1 +i], (16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP); + } + } + for (byte i = 0; i < MAX_LEDS; i++) { + if (pin[GPIO_LED1 +i] < 99) { + pinMode(pin[GPIO_LED1 +i], OUTPUT); + digitalWrite(pin[GPIO_LED1 +i], bitRead(led_inverted, i)); + } + } + for (byte i = 0; i < MAX_SWITCHES; i++) { + if (pin[GPIO_SWT1 +i] < 99) { + pinMode(pin[GPIO_SWT1 +i], (16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 :INPUT_PULLUP); + lastwallswitch[i] = digitalRead(pin[GPIO_SWT1 +i]); // set global now so doesn't change the saved power state on first switch check + } + } + +#ifdef USE_WS2812 + if (!light_type && (pin[GPIO_WS2812] < 99)) { // RGB led + devices_present++; + light_type = LT_WS2812; + } +#endif // USE_WS2812 + if (light_type) { // Any Led light under Dimmer/Color control + LightInit(); + } else { + for (byte i = 0; i < MAX_PWMS; i++) { + if (pin[GPIO_PWM1 +i] < 99) { + pinMode(pin[GPIO_PWM1 +i], OUTPUT); + analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]); + } + } + } + + if (EXS_RELAY == Settings.module) { + SetLatchingRelay(0,2); + SetLatchingRelay(1,2); + } + SetLedPower(Settings.ledstate &8); + +#ifdef USE_IR_REMOTE + if (pin[GPIO_IRSEND] < 99) { + IrSendInit(); + } +#ifdef USE_IR_RECEIVE + if (pin[GPIO_IRRECV] < 99) { + IrReceiveInit(); + } +#endif // USE_IR_RECEIVE +#endif // USE_IR_REMOTE + + CounterInit(); + + hlw_flg = ((pin[GPIO_HLW_SEL] < 99) && (pin[GPIO_HLW_CF1] < 99) && (pin[GPIO_HLW_CF] < 99)); + if (hlw_flg) { + HlwInit(); + } + +#ifdef USE_DHT + if (dht_flg) { + DhtInit(); + } +#endif // USE_DHT + +#ifdef USE_DS18x20 + if (pin[GPIO_DSB] < 99) { + Ds18x20Init(); + } +#endif // USE_DS18x20 } extern "C" { @@ -2731,140 +2712,142 @@ void setup() { byte idx; - Serial.begin(Baudrate); + Serial.begin(baudrate); delay(10); Serial.println(); seriallog_level = LOG_LEVEL_INFO; // Allow specific serial messages until config loaded - snprintf_P(Version, sizeof(Version), PSTR("%d.%d.%d"), VERSION >> 24 & 0xff, VERSION >> 16 & 0xff, VERSION >> 8 & 0xff); + snprintf_P(version, sizeof(version), PSTR("%d.%d.%d"), VERSION >> 24 & 0xff, VERSION >> 16 & 0xff, VERSION >> 8 & 0xff); if (VERSION & 0x1f) { - idx = strlen(Version); - Version[idx] = 96 + (VERSION & 0x1f); - Version[idx +1] = 0; + idx = strlen(version); + version[idx] = 96 + (VERSION & 0x1f); + version[idx +1] = 0; } - CFG_Load(); - CFG_Delta(); + SettingsLoad(); + SettingsDelta(); - osw_init(); + OsWatchInit(); - seriallog_level = sysCfg.seriallog_level; + seriallog_level = Settings.seriallog_level; seriallog_timer = SERIALLOG_TIMER; #ifndef USE_EMULATION - sysCfg.flag.emulation = 0; + Settings.flag.emulation = 0; #endif // USE_EMULATION - syslog_level = (sysCfg.flag.emulation) ? 0 : sysCfg.syslog_level; - stop_flash_rotate = sysCfg.flag.stop_flash_rotate; - savedatacounter = sysCfg.savedata; - sleep = sysCfg.sleep; + syslog_level = (Settings.flag.emulation) ? 0 : Settings.syslog_level; + stop_flash_rotate = Settings.flag.stop_flash_rotate; + save_data_counter = Settings.save_data; + sleep = Settings.sleep; - sysCfg.bootcount++; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), sysCfg.bootcount); - addLog(LOG_LEVEL_DEBUG); + Settings.bootcount++; + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); + AddLog(LOG_LEVEL_DEBUG); - GPIO_init(); + GpioInit(); - if (Serial.baudRate() != Baudrate) { + if (Serial.baudRate() != baudrate) { if (seriallog_level) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_SET_BAUDRATE_TO " %d"), Baudrate); - addLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_SET_BAUDRATE_TO " %d"), baudrate); + AddLog(LOG_LEVEL_INFO); } delay(100); Serial.flush(); - Serial.begin(Baudrate); + Serial.begin(baudrate); delay(10); Serial.println(); } - if (strstr(sysCfg.hostname, "%")) { - strlcpy(sysCfg.hostname, WIFI_HOSTNAME, sizeof(sysCfg.hostname)); - snprintf_P(Hostname, sizeof(Hostname)-1, sysCfg.hostname, sysCfg.mqtt_topic, ESP.getChipId() & 0x1FFF); + if (strstr(Settings.hostname, "%")) { + strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); + snprintf_P(my_hostname, sizeof(my_hostname)-1, Settings.hostname, Settings.mqtt_topic, ESP.getChipId() & 0x1FFF); } else { - snprintf_P(Hostname, sizeof(Hostname)-1, sysCfg.hostname); + snprintf_P(my_hostname, sizeof(my_hostname)-1, Settings.hostname); } - WIFI_Connect(); + WifiConnect(); - getClient(MQTTClient, sysCfg.mqtt_client, sizeof(MQTTClient)); + GetMqttClient(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client)); - if (MOTOR == sysCfg.module) { - sysCfg.poweronstate = 1; // Needs always on else in limbo! + if (MOTOR == Settings.module) { + Settings.poweronstate = 1; // Needs always on else in limbo! } - if (4 == sysCfg.poweronstate) { // Allways on - setRelay(power); + if (4 == Settings.poweronstate) { // Allways on + SetDevicePower(1); } else { if ((resetInfo.reason == REASON_DEFAULT_RST) || (resetInfo.reason == REASON_EXT_SYS_RST)) { - switch (sysCfg.poweronstate) { + switch (Settings.poweronstate) { case 0: // All off power = 0; - setRelay(power); + SetDevicePower(power); break; case 1: // All on - power = (1 << Maxdevice) -1; - setRelay(power); + power = (1 << devices_present) -1; + SetDevicePower(power); break; case 2: // All saved state toggle - power = sysCfg.power & ((1 << Maxdevice) -1) ^ 0xFF; - if (sysCfg.flag.savestate) { - setRelay(power); + power = Settings.power & ((1 << devices_present) -1) ^ POWER_MASK; + if (Settings.flag.save_state) { + SetDevicePower(power); } break; case 3: // All saved state - power = sysCfg.power & ((1 << Maxdevice) -1); - if (sysCfg.flag.savestate) { - setRelay(power); + power = Settings.power & ((1 << devices_present) -1); + if (Settings.flag.save_state) { + SetDevicePower(power); } break; } } else { - power = sysCfg.power & ((1 << Maxdevice) -1); - if (sysCfg.flag.savestate) { - setRelay(power); + power = Settings.power & ((1 << devices_present) -1); + if (Settings.flag.save_state) { + SetDevicePower(power); } } } - // Issue #526 - for (byte i = 0; i < Maxdevice; i++) { - if ((pin[GPIO_REL1 +i] < 99) && (digitalRead(pin[GPIO_REL1 +i]))) { - bitSet(power, i); - pulse_timer[i] = sysCfg.pulsetime[i]; + // Issue #526 and #909 + for (byte i = 0; i < devices_present; i++) { + 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)) { + pulse_timer[i] = Settings.pulse_timer[i]; } } blink_powersave = power; - if (SONOFF_SC == sysCfg.module) { - sc_init(); + if (SONOFF_SC == Settings.module) { + SonoffScInit(); } - rtc_init(); + RtcInit(); snprintf_P(log_data, sizeof(log_data), PSTR(D_PROJECT " %s %s (" D_CMND_TOPIC " %s, " D_FALLBACK " %s, " D_CMND_GROUPTOPIC " %s) " D_VERSION " %s"), - PROJECT, sysCfg.friendlyname[0], sysCfg.mqtt_topic, MQTTClient, sysCfg.mqtt_grptopic, Version); - addLog(LOG_LEVEL_INFO); + PROJECT, Settings.friendlyname[0], Settings.mqtt_topic, mqtt_client, Settings.mqtt_grptopic, version); + AddLog(LOG_LEVEL_INFO); } void loop() { - osw_loop(); + OsWatchLoop(); #ifdef USE_WEBSERVER - pollDnsWeb(); + PollDnsWebserver(); #endif // USE_WEBSERVER #ifdef USE_EMULATION - if (sysCfg.flag.emulation) { - pollUDP(); + if (Settings.flag.emulation) { + PollUdp(); } #endif // USE_EMULATION - if (millis() >= timerxs) { - stateloop(); + if (millis() >= state_loop_timer) { + StateLoop(); } - if (sysCfg.flag.mqtt_enabled) { - mqttClient.loop(); + if (Settings.flag.mqtt_enabled) { + MqttClient.loop(); } if (Serial.available()){ - serial(); + SerialInput(); } // yield(); // yield == delay(0), delay contains yield, auto yield in loop diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h new file mode 100644 index 000000000..9f7259e54 --- /dev/null +++ b/sonoff/sonoff_post.h @@ -0,0 +1,102 @@ +/* + sonoff_post.h - Post header file for Sonoff-Tasmota + + Copyright (C) 2017 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 + 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 _SONOFF_POST_H_ +#define _SONOFF_POST_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "user_interface.h" + +// Function prototypes +void WifiWpsStatusCallback(wps_cb_status status); + +#ifdef __cplusplus +} +#endif + +#define USE_DHT // Default DHT11 sensor needs no external library +#ifndef USE_DS18x20 +#define USE_DS18B20 // Default DS18B20 sensor needs no external library +#endif +//#define DEBUG_THEO // Add debug code + +#ifdef BE_MINIMAL +#ifdef USE_MQTT_TLS +#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set +#endif +#ifdef USE_DISCOVERY +#undef USE_DISCOVERY // Disable Discovery services for both MQTT and web server +#endif +#ifdef USE_DOMOTICZ +#undef USE_DOMOTICZ // Disable Domoticz +#endif +//#ifdef USE_WEBSERVER +//#undef USE_WEBSERVER // Disable Webserver +//#endif +#ifdef USE_EMULATION +#undef USE_EMULATION // Disable Wemo or Hue emulation +#endif +#ifdef USE_DS18x20 +#undef USE_DS18x20 // Disable DS18x20 sensor +#endif +#ifdef USE_I2C +#undef USE_I2C // Disable all I2C sensors and devices +#endif +#ifdef USE_SPI +#undef USE_SPI // Disable all SPI devices +#endif +#ifdef USE_WS2812 +#undef USE_WS2812 // Disable WS2812 Led string +#endif +#ifdef USE_DS18B20 +#undef USE_DS18B20 // Disable internal DS18B20 sensor +#endif +#ifdef USE_DHT +#undef USE_DHT // Disable internal DHT sensor +#endif +#ifdef USE_IR_REMOTE +#undef USE_IR_REMOTE // Disable IR driver +#endif +#ifdef DEBUG_THEO +#undef DEBUG_THEO // Disable debug code +#endif +#endif // BE_MINIMAL + +#ifndef SWITCH_MODE +#define SWITCH_MODE TOGGLE // TOGGLE, FOLLOW or FOLLOW_INV (the wall switch state) +#endif + +#ifndef MQTT_FINGERPRINT +#define MQTT_FINGERPRINT "A5 02 FF 13 99 9F 8B 39 8E F1 83 4F 11 23 65 0B 32 36 FC 07" +#endif + +#ifndef WS2812_LEDS +#define WS2812_LEDS 30 // [Pixels] Number of LEDs +#endif + +#ifndef MESSZ +#define MESSZ 405 // Max number of characters in JSON message string (4 x DS18x20 sensors) +#endif + + + +#endif // _SONOFF_POST_H_ \ No newline at end of file diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 8b092b20d..cb47420cf 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -17,8 +17,11 @@ along with this program. If not, see . */ +#ifndef _SONOFF_TEMPLATE_H_ +#define _SONOFF_TEMPLATE_H_ + // User selectable GPIO functionality -enum upins_t { +enum UserSelectablePins { GPIO_NONE, // Not used GPIO_DHT11, // DHT11 GPIO_DHT21, // DHT21, AM2301 @@ -40,10 +43,33 @@ enum upins_t { GPIO_REL2, GPIO_REL3, GPIO_REL4, + GPIO_REL5, + GPIO_REL6, + GPIO_REL7, + GPIO_REL8, GPIO_REL1_INV, GPIO_REL2_INV, GPIO_REL3_INV, GPIO_REL4_INV, + GPIO_REL5_INV, + GPIO_REL6_INV, + GPIO_REL7_INV, + GPIO_REL8_INV, + GPIO_PWM1, // RGB Red or C Cold White + GPIO_PWM2, // RGB Green or CW Warm White + GPIO_PWM3, // RGB Blue + GPIO_PWM4, // RGBW (Cold) White + GPIO_PWM5, // RGBCW Warm White + GPIO_CNTR1, + GPIO_CNTR2, + GPIO_CNTR3, + GPIO_CNTR4, + GPIO_PWM1_INV, // RGB Red or C Cold White + GPIO_PWM2_INV, // RGB Green or CW Warm White + GPIO_PWM3_INV, // RGB Blue + GPIO_PWM4_INV, // RGBW (Cold) White + GPIO_PWM5_INV, // RGBCW Warm White + GPIO_IRRECV, // IR receiver GPIO_LED1, // Leds GPIO_LED2, GPIO_LED3, @@ -52,19 +78,10 @@ enum upins_t { GPIO_LED2_INV, GPIO_LED3_INV, GPIO_LED4_INV, - GPIO_PWM1, // Sonoff Led Cold - GPIO_PWM2, // Sonoff Led Warm - GPIO_PWM3, // Red (swapped with Blue from original) - GPIO_PWM4, // Green - GPIO_PWM5, // Blue (swapped with Red from original) - GPIO_CNTR1, - GPIO_CNTR2, - GPIO_CNTR3, - GPIO_CNTR4, GPIO_SENSOR_END }; // Text in webpage Module Parameters and commands GPIOS and GPIO -const char sensors[GPIO_SENSOR_END][9] PROGMEM = { +const char kSensors[GPIO_SENSOR_END][9] PROGMEM = { D_SENSOR_NONE, D_SENSOR_DHT11, D_SENSOR_AM2301, @@ -73,7 +90,7 @@ const char sensors[GPIO_SENSOR_END][9] PROGMEM = { D_SENSOR_I2C_SCL, D_SENSOR_I2C_SDA, D_SENSOR_WS2812, - D_SENSOR_IRREMOTE, + D_SENSOR_IRSEND, D_SENSOR_SWITCH "1", D_SENSOR_SWITCH "2", D_SENSOR_SWITCH "3", @@ -86,18 +103,18 @@ const char sensors[GPIO_SENSOR_END][9] PROGMEM = { D_SENSOR_RELAY "2", D_SENSOR_RELAY "3", D_SENSOR_RELAY "4", - D_SENSOR_RELAY "1I", - D_SENSOR_RELAY "2I", - D_SENSOR_RELAY "3I", - D_SENSOR_RELAY "4I", - D_SENSOR_LED "1", - D_SENSOR_LED "2", - D_SENSOR_LED "3", - D_SENSOR_LED "4", - D_SENSOR_LED "1I", - D_SENSOR_LED "2I", - D_SENSOR_LED "3I", - D_SENSOR_LED "4I", + D_SENSOR_RELAY "5", + D_SENSOR_RELAY "6", + D_SENSOR_RELAY "7", + D_SENSOR_RELAY "8", + D_SENSOR_RELAY "1i", + D_SENSOR_RELAY "2i", + D_SENSOR_RELAY "3i", + D_SENSOR_RELAY "4i", + D_SENSOR_RELAY "5i", + D_SENSOR_RELAY "6i", + D_SENSOR_RELAY "7i", + D_SENSOR_RELAY "8i", D_SENSOR_PWM "1", D_SENSOR_PWM "2", D_SENSOR_PWM "3", @@ -106,11 +123,25 @@ const char sensors[GPIO_SENSOR_END][9] PROGMEM = { D_SENSOR_COUNTER "1", D_SENSOR_COUNTER "2", D_SENSOR_COUNTER "3", - D_SENSOR_COUNTER "4" - }; + D_SENSOR_COUNTER "4", + D_SENSOR_PWM "1i", + D_SENSOR_PWM "2i", + D_SENSOR_PWM "3i", + D_SENSOR_PWM "4i", + D_SENSOR_PWM "5i", + D_SENSOR_IRRECV, + D_SENSOR_LED "1", + D_SENSOR_LED "2", + D_SENSOR_LED "3", + D_SENSOR_LED "4", + D_SENSOR_LED "1i", + D_SENSOR_LED "2i", + D_SENSOR_LED "3i", + D_SENSOR_LED "4i" +}; // Programmer selectable GPIO functionality offset by user selectable GPIOs -enum fpins_t { +enum ProgramSelectablePins { GPIO_RXD = GPIO_SENSOR_END, // Serial interface GPIO_TXD, // Serial interface GPIO_HLW_SEL, // HLW8012 Sel output (Sonoff Pow) @@ -125,7 +156,7 @@ enum fpins_t { /********************************************************************************************/ // Supported hardware modules -enum module_t { +enum SupportedModules { SONOFF_BASIC, SONOFF_RF, SONOFF_SV, @@ -159,12 +190,18 @@ enum module_t { SUPLA1, WITTY, YUNSHAN, + MAGICHOME, + LUANIHVIO, + KMC_70011, + ARILUX, MAXMODULE }; /********************************************************************************************/ #define MAX_GPIO_PIN 18 // Number of supported GPIO +const char PINS_WEMOS[] PROGMEM = "D3TXD4RXD2D1flashcontrolD6D7D5D8D0A0"; + typedef struct MYIO { uint8_t io[MAX_GPIO_PIN]; } myio; @@ -174,7 +211,7 @@ typedef struct MYTMPLT { myio gp; } mytmplt; -const uint8_t nicelist[MAXMODULE] PROGMEM = { +const uint8_t kNiceList[MAXMODULE] PROGMEM = { SONOFF_BASIC, SONOFF_RF, SONOFF_TH, @@ -201,17 +238,21 @@ const uint8_t nicelist[MAXMODULE] PROGMEM = { ELECTRODRAGON, EXS_RELAY, SUPLA1, + LUANIHVIO, YUNSHAN, WION, H801, + MAGICHOME, + ARILUX, HUAFAN_SS, + KMC_70011, AILIGHT, WEMOS, WITTY }; // Default module settings -const mytmplt modules[MAXMODULE] PROGMEM = { +const mytmplt kModules[MAXMODULE] PROGMEM = { { "Sonoff Basic", // Sonoff Basic (ESP8266) GPIO_KEY1, // GPIO00 Button GPIO_USER, // GPIO01 Serial RXD and Optional sensor @@ -465,13 +506,13 @@ const mytmplt modules[MAXMODULE] PROGMEM = { GPIO_LED1, // GPIO01 Green LED GPIO_TXD, // GPIO02 RX - Pin next to TX on the PCB GPIO_RXD, // GPIO03 TX - Pin next to GND on the PCB - GPIO_PWM2, // GPIO04 W2 + GPIO_USER, // GPIO04 W2 - PWM5 GPIO_LED2_INV, // GPIO05 Red LED 0, 0, 0, 0, 0, 0, // Flash connection GPIO_PWM3, // GPIO12 Blue - GPIO_PWM4, // GPIO13 Green - GPIO_PWM1, // GPIO14 W1 - GPIO_PWM5, // GPIO15 Red + GPIO_PWM2, // GPIO13 Green + GPIO_USER, // GPIO14 W1 - PWM4 + GPIO_PWM1, // GPIO15 Red 0, 0 }, { "Sonoff SC", // Sonoff SC (ESP8266) @@ -633,10 +674,10 @@ const mytmplt modules[MAXMODULE] PROGMEM = { GPIO_KEY1, // GPIO04 D2 push button on ESP-12F board GPIO_USER, // GPIO05 D1 optional sensor 0, 0, 0, 0, 0, 0, // Flash connection - GPIO_PWM4, // GPIO12 D6 RGB LED Green - GPIO_PWM5, // GPIO13 D7 RGB LED Blue + GPIO_PWM2, // GPIO12 D6 RGB LED Green + GPIO_PWM3, // GPIO13 D7 RGB LED Blue GPIO_USER, // GPIO14 D5 optional sensor - GPIO_PWM3, // GPIO15 D8 RGB LED Red + GPIO_PWM1, // GPIO15 D8 RGB LED Red GPIO_USER, // GPIO16 D0 optional sensor GPIO_ADC0 // ADC0 A0 Light sensor / Requires USE_ADC_VCC in user_config.h to be disabled }, @@ -650,6 +691,55 @@ const mytmplt modules[MAXMODULE] PROGMEM = { GPIO_KEY1, // GPIO05 Blue Led and OptoCoupler input - Module Pin 9 0, 0, 0, 0, 0, 0, // Flash connection 0, 0, 0, 0, 0 + }, + { "MagicHome", // Magic Home (aka Flux-light) (ESP8266) - https://www.aliexpress.com/item/Magic-Home-Mini-RGB-RGBW-Wifi-Controller-For-Led-Strip-Panel-light-Timing-Function-16million-colors/32686853650.html + 0, 0, + GPIO_LED1_INV, // GPIO02 Blue onboard LED + 0, + GPIO_USER, // GPIO04 IR receiver (optional) + GPIO_PWM2, // GPIO05 RGB LED Green + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_PWM3, // GPIO12 RGB LED Blue + GPIO_USER, // GPIO13 RGBW LED White (optional - set to PWM4 for Cold White or Warm White) + GPIO_PWM1, // GPIO14 RGB LED Red + 0, 0, 0 + }, + { "Luani HVIO", // ESP8266_HVIO - https://luani.de/projekte/esp8266-hvio/ + 0, // GPIO00 Flash jumper + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Optional sensor / I2C SDA pad + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_REL1, // GPIO04 Relay 1 (0 = Off, 1 = On) + GPIO_REL2, // GPIO05 Relay 2 (0 = Off, 1 = On) + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_SWT1, // GPIO12 External input 1 (0 = On, 1 = Off) + GPIO_SWT2, // GPIO13 External input 2 (0 = On, 1 = Off) + GPIO_USER, // GPIO14 Optional sensor / I2C SCL pad + GPIO_LED1, // GPIO15 Led (1 = On, 0 = Off) + 0, + GPIO_ADC0 // ADC0 A0 Analog input + }, + { "KMC 70011", // KMC 70011 (https://www.amazon.com/KMC-Timing-Monitoring-Network-125V-240V/dp/B06XRX2GTQ) + GPIO_KEY1, // GPIO00 Button + 0, 0, 0, + GPIO_HLW_CF, // GPIO04 HLW8012 CF + GPIO_HLW_CF1, // GPIO05 HLW8012 CF1 + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_HLW_SEL, // GPIO12 HLW8012 SEL + GPIO_LED1_INV, // GPIO13 Green Led + GPIO_REL1, // GPIO14 Relay + 0, 0, 0 + }, + { "Arilux", // Arilux AL-LC01 (ESP8285) - https://www.banggood.com/nl/ARILUX-AL-LC01-Super-Mini-LED-WIFI-Smart-RGB-Controller-For-RGB-LED-Strip-Light-DC-9-12V-p-1058603.html + 0, 0, 0, 0, // (PwmFrequency 1111Hz) + GPIO_USER, // GPIO04 IR or RF receiver (optional) + GPIO_PWM1, // GPIO05 RGB LED Red + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_PWM2, // GPIO12 RGB LED Green + GPIO_PWM3, // GPIO13 RGB LED Blue + GPIO_USER, // GPIO14 RGBW LED White (optional - set to PWM4 for Cold White or Warm White) + 0, 0, 0 } }; +#endif // _SONOFF_TEMPLATE_H_ \ No newline at end of file diff --git a/sonoff/support.h b/sonoff/support.h deleted file mode 100644 index 4cd6cede3..000000000 --- a/sonoff/support.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - support.h - parameters used by platformio for Sonoff-Tasmota - - Copyright (C) 2017 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 - 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 . -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __SUPPORT_H__ -#define __SUPPORT_H__ - -#include "user_interface.h" - -/* Function prototypes. */ -void WIFI_wps_status_cb(wps_cb_status status); - -#endif // ifndef __SUPPORT_H__ - -#ifdef __cplusplus -} -#endif diff --git a/sonoff/support.ino b/sonoff/support.ino index 9c65d3513..f48e2d1de 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -17,6 +17,9 @@ along with this program. If not, see . */ +IPAddress syslog_host_addr; // Syslog host IP address +unsigned long syslog_host_refresh = 0; + /*********************************************************************************************\ * Watchdog extension (https://github.com/esp8266/Arduino/issues/1532) \*********************************************************************************************/ @@ -25,49 +28,49 @@ Ticker tickerOSWatch; #define OSWATCH_RESET_TIME 30 -static unsigned long osw_last_loop; -byte osw_flag = 0; +static unsigned long oswatch_last_loop_time; +byte oswatch_blocked_loop = 0; #ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves exception -void osw_osWatch() ICACHE_RAM_ATTR; +void OsWatchTicker() ICACHE_RAM_ATTR; #endif // USE_WS2812_DMA -void osw_osWatch() +void OsWatchTicker() { unsigned long t = millis(); - unsigned long last_run = abs(t - osw_last_loop); + unsigned long last_run = abs(t - oswatch_last_loop_time); #ifdef DEBUG_THEO - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d, last_run %d"), ESP.getFreeHeap(), WIFI_getRSSIasQuality(WiFi.RSSI()), last_run); - addLog(LOG_LEVEL_DEBUG); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d, last_run %d"), ESP.getFreeHeap(), WifiGetRssiAsQuality(WiFi.RSSI()), last_run); + AddLog(LOG_LEVEL_DEBUG); #endif // DEBUG_THEO if (last_run >= (OSWATCH_RESET_TIME * 1000)) { - addLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_OSWATCH " " D_BLOCKED_LOOP ". " D_RESTARTING)); - rtcMem.osw_flag = 1; - RTC_Save(); + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_OSWATCH " " D_BLOCKED_LOOP ". " D_RESTARTING)); + RtcSettings.oswatch_blocked_loop = 1; + RtcSettingsSave(); // ESP.restart(); // normal reboot ESP.reset(); // hard reset } } -void osw_init() +void OsWatchInit() { - osw_flag = rtcMem.osw_flag; - rtcMem.osw_flag = 0; - osw_last_loop = millis(); - tickerOSWatch.attach_ms(((OSWATCH_RESET_TIME / 3) * 1000), osw_osWatch); + oswatch_blocked_loop = RtcSettings.oswatch_blocked_loop; + RtcSettings.oswatch_blocked_loop = 0; + oswatch_last_loop_time = millis(); + tickerOSWatch.attach_ms(((OSWATCH_RESET_TIME / 3) * 1000), OsWatchTicker); } -void osw_loop() +void OsWatchLoop() { - osw_last_loop = millis(); + oswatch_last_loop_time = millis(); // while(1) delay(1000); // this will trigger the os watch } -String getResetReason() +String GetResetReason() { char buff[32]; - if (osw_flag) { + if (oswatch_blocked_loop) { strncpy_P(buff, PSTR(D_BLOCKED_LOOP), sizeof(buff)); return String(buff); } else { @@ -76,7 +79,7 @@ String getResetReason() } #ifdef DEBUG_THEO -void exception_tst(byte type) +void ExceptionTest(byte type) { /* Exception (28): @@ -116,7 +119,7 @@ Decoding 14 results 0x4021ffb4: snprintf_P(char*, unsigned int, char const*, ...) at C:\Data2\Arduino\arduino-1.8.1-esp-2.3.0\portable\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/pgmspace.cpp line 146 0x40201118: atol at C:\Data2\Arduino\arduino-1.8.1-esp-2.3.0\portable\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/core_esp8266_noniso.c line 45 0x40201128: atoi at C:\Data2\Arduino\arduino-1.8.1-esp-2.3.0\portable\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/core_esp8266_noniso.c line 45 -0x4020fafb: mqttDataCb(char*, unsigned char*, unsigned int) at R:\Arduino\Work-ESP8266\Theo\sonoff\sonoff-4\sonoff/sonoff.ino line 679 (discriminator 1) +0x4020fafb: MqttDataCallback(char*, unsigned char*, unsigned int) at R:\Arduino\Work-ESP8266\Theo\sonoff\sonoff-4\sonoff/sonoff.ino line 679 (discriminator 1) 0x4022321b: pp_attach at ?? line ? 00:00:08 MQTT: tele/sonoff/INFO3 = {"Started":"Fatal exception:28 flag:2 (EXCEPTION) epc1:0x4000bf64 epc2:0x00000000 epc3:0x00000000 excvaddr:0x00000007 depc:0x00000000"} @@ -224,7 +227,7 @@ char* dtostrfi(double number, unsigned char prec, char *s) // Use localized deci return _dtostrf(number, prec, s, 1); } -boolean parseIP(uint32_t* addr, const char* str) +boolean ParseIp(uint32_t* addr, const char* str) { uint8_t *part = (uint8_t*)addr; byte i; @@ -241,7 +244,7 @@ boolean parseIP(uint32_t* addr, const char* str) return (3 == i); } -void mqttfy(byte option, char* str) +void MakeValidMqtt(byte option, char* str) { // option 0 = replace by underscore // option 1 = delete character @@ -265,7 +268,7 @@ void mqttfy(byte option, char* str) } // Function to parse & check if version_str is newer than our currently installed version. -bool newerVersion(char* version_str) +bool NewerVersion(char* version_str) { uint32_t version = 0; uint8_t i = 0; @@ -308,21 +311,21 @@ bool newerVersion(char* version_str) return (version > VERSION); } -char* getPowerDevice(char* dest, uint8_t idx, size_t size, uint8_t option) +char* GetPowerDevice(char* dest, uint8_t idx, size_t size, uint8_t option) { char sidx[8]; strncpy_P(dest, S_RSLT_POWER, size); - if ((Maxdevice + option) > 1) { + if ((devices_present + option) > 1) { snprintf_P(sidx, sizeof(sidx), PSTR("%d"), idx); strncat(dest, sidx, size); } return dest; } -char* getPowerDevice(char* dest, uint8_t idx, size_t size) +char* GetPowerDevice(char* dest, uint8_t idx, size_t size) { - return getPowerDevice(dest, idx, size, 0); + return GetPowerDevice(dest, idx, size, 0); } /*********************************************************************************************\ @@ -334,42 +337,42 @@ char* getPowerDevice(char* dest, uint8_t idx, size_t size) #define WIFI_CHECK_SEC 20 // seconds #define WIFI_RETRY_SEC 30 // seconds -uint8_t _wificounter; -uint8_t _wifiretry; -uint8_t _wifistatus; -uint8_t _wpsresult; -uint8_t _wificonfigflag = 0; -uint8_t _wifiConfigCounter = 0; +uint8_t wifi_counter; +uint8_t wifi_retry; +uint8_t wifi_status; +uint8_t wps_result; +uint8_t wifi_config_type = 0; +uint8_t wifi_config_counter = 0; -int WIFI_getRSSIasQuality(int RSSI) +int WifiGetRssiAsQuality(int rssi) { int quality = 0; - if (RSSI <= -100) { + if (rssi <= -100) { quality = 0; - } else if (RSSI >= -50) { + } else if (rssi >= -50) { quality = 100; } else { - quality = 2 * (RSSI + 100); + quality = 2 * (rssi + 100); } return quality; } -boolean WIFI_configCounter() +boolean WifiConfigCounter() { - if (_wifiConfigCounter) { - _wifiConfigCounter = WIFI_MANAGER_SEC; + if (wifi_config_counter) { + wifi_config_counter = WIFI_MANAGER_SEC; } - return (_wifiConfigCounter); + return (wifi_config_counter); } extern "C" { #include "user_interface.h" } -void WIFI_wps_status_cb(wps_cb_status status); +void WifiWpsStatusCallback(wps_cb_status status); -void WIFI_wps_status_cb(wps_cb_status status) +void WifiWpsStatusCallback(wps_cb_status status) { /* from user_interface.h: enum wps_cb_status { @@ -380,31 +383,31 @@ void WIFI_wps_status_cb(wps_cb_status status) WPS_CB_ST_SCAN_ERR, // can not find the target WPS AP }; */ - _wpsresult = status; - if (WPS_CB_ST_SUCCESS == _wpsresult) { + wps_result = status; + if (WPS_CB_ST_SUCCESS == wps_result) { wifi_wps_disable(); } else { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_WPS_FAILED_WITH_STATUS " %d"), _wpsresult); - addLog(LOG_LEVEL_DEBUG); - _wifiConfigCounter = 2; + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_WPS_FAILED_WITH_STATUS " %d"), wps_result); + AddLog(LOG_LEVEL_DEBUG); + wifi_config_counter = 2; } } -boolean WIFI_WPSConfigDone(void) +boolean WifiWpsConfigDone(void) { - return (!_wpsresult); + return (!wps_result); } -boolean WIFI_beginWPSConfig(void) +boolean WifiWpsConfigBegin(void) { - _wpsresult = 99; + wps_result = 99; if (!wifi_wps_disable()) { return false; } if (!wifi_wps_enable(WPS_TYPE_PBC)) { return false; // so far only WPS_TYPE_PBC is supported (SDK 2.0.0) } - if (!wifi_set_wps_cb((wps_st_cb_t) &WIFI_wps_status_cb)) { + if (!wifi_set_wps_cb((wps_st_cb_t) &WifiWpsStatusCallback)) { return false; } if (!wifi_wps_start()) { @@ -413,58 +416,58 @@ boolean WIFI_beginWPSConfig(void) return true; } -void WIFI_config(uint8_t type) +void WifiConfig(uint8_t type) { - if (!_wificonfigflag) { + if (!wifi_config_type) { if (type >= WIFI_RETRY) { // WIFI_RETRY and WIFI_WAIT return; } #ifdef USE_EMULATION - UDP_Disconnect(); + UdpDisconnect(); #endif // USE_EMULATION WiFi.disconnect(); // Solve possible Wifi hangs - _wificonfigflag = type; - _wifiConfigCounter = WIFI_CONFIG_SEC; // Allow up to WIFI_CONFIG_SECS seconds for phone to provide ssid/pswd - _wificounter = _wifiConfigCounter +5; + wifi_config_type = type; + wifi_config_counter = WIFI_CONFIG_SEC; // Allow up to WIFI_CONFIG_SECS seconds for phone to provide ssid/pswd + wifi_counter = wifi_config_counter +5; blinks = 1999; - if (WIFI_RESTART == _wificonfigflag) { - restartflag = 2; + if (WIFI_RESTART == wifi_config_type) { + restart_flag = 2; } - else if (WIFI_SMARTCONFIG == _wificonfigflag) { - addLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_1_SMARTCONFIG D_ACTIVE_FOR_1_MINUTE)); + else if (WIFI_SMARTCONFIG == wifi_config_type) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_1_SMARTCONFIG D_ACTIVE_FOR_1_MINUTE)); WiFi.beginSmartConfig(); } - else if (WIFI_WPSCONFIG == _wificonfigflag) { - if (WIFI_beginWPSConfig()) { - addLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_3_WPSCONFIG D_ACTIVE_FOR_1_MINUTE)); + else if (WIFI_WPSCONFIG == wifi_config_type) { + if (WifiWpsConfigBegin()) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_3_WPSCONFIG D_ACTIVE_FOR_1_MINUTE)); } else { - addLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_3_WPSCONFIG D_FAILED_TO_START)); - _wifiConfigCounter = 3; + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_3_WPSCONFIG D_FAILED_TO_START)); + wifi_config_counter = 3; } } #ifdef USE_WEBSERVER - else if (WIFI_MANAGER == _wificonfigflag) { - addLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_2_WIFIMANAGER D_ACTIVE_FOR_1_MINUTE)); - beginWifiManager(); + else if (WIFI_MANAGER == wifi_config_type) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_2_WIFIMANAGER D_ACTIVE_FOR_1_MINUTE)); + WifiManagerBegin(); } #endif // USE_WEBSERVER } } -void WIFI_begin(uint8_t flag) +void WifiBegin(uint8_t flag) { - const char PhyMode[] = " BGN"; + const char kWifiPhyMode[] = " BGN"; #ifdef USE_EMULATION - UDP_Disconnect(); + UdpDisconnect(); #endif // USE_EMULATION if (!strncmp_P(ESP.getSdkVersion(),PSTR("1.5.3"),5)) { - addLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_PATCH_ISSUE_2186)); + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_PATCH_ISSUE_2186)); WiFi.mode(WIFI_OFF); // See https://github.com/esp8266/Arduino/issues/2186 } WiFi.disconnect(); WiFi.mode(WIFI_STA); // Disable AP mode - if (sysCfg.sleep) { + if (Settings.sleep) { WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times } // if (WiFi.getPhyMode() != WIFI_PHY_MODE_11N) { @@ -477,189 +480,189 @@ void WIFI_begin(uint8_t flag) switch (flag) { case 0: // AP1 case 1: // AP2 - sysCfg.sta_active = flag; + Settings.sta_active = flag; break; case 2: // Toggle - sysCfg.sta_active ^= 1; + Settings.sta_active ^= 1; } // 3: Current AP - if (0 == strlen(sysCfg.sta_ssid[1])) { - sysCfg.sta_active = 0; + if (0 == strlen(Settings.sta_ssid[1])) { + Settings.sta_active = 0; } - if (sysCfg.ip_address[0]) { - WiFi.config(sysCfg.ip_address[0], sysCfg.ip_address[1], sysCfg.ip_address[2], sysCfg.ip_address[3]); // Set static IP + if (Settings.ip_address[0]) { + WiFi.config(Settings.ip_address[0], Settings.ip_address[1], Settings.ip_address[2], Settings.ip_address[3]); // Set static IP } - WiFi.hostname(Hostname); - WiFi.begin(sysCfg.sta_ssid[sysCfg.sta_active], sysCfg.sta_pwd[sysCfg.sta_active]); + WiFi.hostname(my_hostname); + WiFi.begin(Settings.sta_ssid[Settings.sta_active], Settings.sta_pwd[Settings.sta_active]); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s " D_IN_MODE " 11%c " D_AS " %s..."), - sysCfg.sta_active +1, sysCfg.sta_ssid[sysCfg.sta_active], PhyMode[WiFi.getPhyMode() & 0x3], Hostname); - addLog(LOG_LEVEL_INFO); + Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); + AddLog(LOG_LEVEL_INFO); } -void WIFI_check_ip() +void WifiCheckIp() { if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { - _wificounter = WIFI_CHECK_SEC; - _wifiretry = WIFI_RETRY_SEC; - addLog_P((_wifistatus != WL_CONNECTED) ? LOG_LEVEL_INFO : LOG_LEVEL_DEBUG_MORE, S_LOG_WIFI, PSTR(D_CONNECTED)); - if (_wifistatus != WL_CONNECTED) { -// addLog_P(LOG_LEVEL_INFO, PSTR("Wifi: Set IP addresses")); - sysCfg.ip_address[1] = (uint32_t)WiFi.gatewayIP(); - sysCfg.ip_address[2] = (uint32_t)WiFi.subnetMask(); - sysCfg.ip_address[3] = (uint32_t)WiFi.dnsIP(); + wifi_counter = WIFI_CHECK_SEC; + wifi_retry = WIFI_RETRY_SEC; + AddLog_P((wifi_status != WL_CONNECTED) ? LOG_LEVEL_INFO : LOG_LEVEL_DEBUG_MORE, S_LOG_WIFI, PSTR(D_CONNECTED)); + if (wifi_status != WL_CONNECTED) { +// AddLog_P(LOG_LEVEL_INFO, PSTR("Wifi: Set IP addresses")); + Settings.ip_address[1] = (uint32_t)WiFi.gatewayIP(); + Settings.ip_address[2] = (uint32_t)WiFi.subnetMask(); + Settings.ip_address[3] = (uint32_t)WiFi.dnsIP(); } - _wifistatus = WL_CONNECTED; + wifi_status = WL_CONNECTED; } else { - _wifistatus = WiFi.status(); - switch (_wifistatus) { + wifi_status = WiFi.status(); + switch (wifi_status) { case WL_CONNECTED: - addLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_NO_IP_ADDRESS)); - _wifistatus = 0; - _wifiretry = WIFI_RETRY_SEC; + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_NO_IP_ADDRESS)); + wifi_status = 0; + wifi_retry = WIFI_RETRY_SEC; break; case WL_NO_SSID_AVAIL: - addLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_NOT_REACHED)); - if (WIFI_WAIT == sysCfg.sta_config) { - _wifiretry = WIFI_RETRY_SEC; + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_NOT_REACHED)); + if (WIFI_WAIT == Settings.sta_config) { + wifi_retry = WIFI_RETRY_SEC; } else { - if (_wifiretry > (WIFI_RETRY_SEC / 2)) { - _wifiretry = WIFI_RETRY_SEC / 2; + if (wifi_retry > (WIFI_RETRY_SEC / 2)) { + wifi_retry = WIFI_RETRY_SEC / 2; } - else if (_wifiretry) { - _wifiretry = 0; + else if (wifi_retry) { + wifi_retry = 0; } } break; case WL_CONNECT_FAILED: - addLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_WRONG_PASSWORD)); - if (_wifiretry > (WIFI_RETRY_SEC / 2)) { - _wifiretry = WIFI_RETRY_SEC / 2; + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_WRONG_PASSWORD)); + if (wifi_retry > (WIFI_RETRY_SEC / 2)) { + wifi_retry = WIFI_RETRY_SEC / 2; } - else if (_wifiretry) { - _wifiretry = 0; + else if (wifi_retry) { + wifi_retry = 0; } break; default: // WL_IDLE_STATUS and WL_DISCONNECTED - if (!_wifiretry || ((WIFI_RETRY_SEC / 2) == _wifiretry)) { - addLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT)); + if (!wifi_retry || ((WIFI_RETRY_SEC / 2) == wifi_retry)) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT)); } else { - addLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_ATTEMPTING_CONNECTION)); + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_ATTEMPTING_CONNECTION)); } } - if (_wifiretry) { - if (WIFI_RETRY_SEC == _wifiretry) { - WIFI_begin(3); // Select default SSID + if (wifi_retry) { + if (WIFI_RETRY_SEC == wifi_retry) { + WifiBegin(3); // Select default SSID } - if ((sysCfg.sta_config != WIFI_WAIT) && ((WIFI_RETRY_SEC / 2) == _wifiretry)) { - WIFI_begin(2); // Select alternate SSID + if ((Settings.sta_config != WIFI_WAIT) && ((WIFI_RETRY_SEC / 2) == wifi_retry)) { + WifiBegin(2); // Select alternate SSID } - _wificounter = 1; - _wifiretry--; + wifi_counter = 1; + wifi_retry--; } else { - WIFI_config(sysCfg.sta_config); - _wificounter = 1; - _wifiretry = WIFI_RETRY_SEC; + WifiConfig(Settings.sta_config); + wifi_counter = 1; + wifi_retry = WIFI_RETRY_SEC; } } } -void WIFI_Check(uint8_t param) +void WifiCheck(uint8_t param) { - _wificounter--; + wifi_counter--; switch (param) { case WIFI_SMARTCONFIG: case WIFI_MANAGER: case WIFI_WPSCONFIG: - WIFI_config(param); + WifiConfig(param); break; default: - if (_wifiConfigCounter) { - _wifiConfigCounter--; - _wificounter = _wifiConfigCounter +5; - if (_wifiConfigCounter) { - if ((WIFI_SMARTCONFIG == _wificonfigflag) && WiFi.smartConfigDone()) { - _wifiConfigCounter = 0; + if (wifi_config_counter) { + wifi_config_counter--; + wifi_counter = wifi_config_counter +5; + if (wifi_config_counter) { + if ((WIFI_SMARTCONFIG == wifi_config_type) && WiFi.smartConfigDone()) { + wifi_config_counter = 0; } - if ((WIFI_WPSCONFIG == _wificonfigflag) && WIFI_WPSConfigDone()) { - _wifiConfigCounter = 0; + if ((WIFI_WPSCONFIG == wifi_config_type) && WifiWpsConfigDone()) { + wifi_config_counter = 0; } - if (!_wifiConfigCounter) { + if (!wifi_config_counter) { if (strlen(WiFi.SSID().c_str())) { - strlcpy(sysCfg.sta_ssid[0], WiFi.SSID().c_str(), sizeof(sysCfg.sta_ssid[0])); + strlcpy(Settings.sta_ssid[0], WiFi.SSID().c_str(), sizeof(Settings.sta_ssid[0])); } if (strlen(WiFi.psk().c_str())) { - strlcpy(sysCfg.sta_pwd[0], WiFi.psk().c_str(), sizeof(sysCfg.sta_pwd[0])); + strlcpy(Settings.sta_pwd[0], WiFi.psk().c_str(), sizeof(Settings.sta_pwd[0])); } - sysCfg.sta_active = 0; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_WCFG_1_SMARTCONFIG D_CMND_SSID "1 %s, " D_CMND_PASSWORD "1 %s"), sysCfg.sta_ssid[0], sysCfg.sta_pwd[0]); - addLog(LOG_LEVEL_INFO); + Settings.sta_active = 0; + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_WCFG_1_SMARTCONFIG D_CMND_SSID "1 %s, " D_CMND_PASSWORD "1 %s"), Settings.sta_ssid[0], Settings.sta_pwd[0]); + AddLog(LOG_LEVEL_INFO); } } - if (!_wifiConfigCounter) { - if (WIFI_SMARTCONFIG == _wificonfigflag) { + if (!wifi_config_counter) { + if (WIFI_SMARTCONFIG == wifi_config_type) { WiFi.stopSmartConfig(); } - restartflag = 2; + restart_flag = 2; } } else { - if (_wificounter <= 0) { - addLog_P(LOG_LEVEL_DEBUG_MORE, S_LOG_WIFI, PSTR(D_CHECKING_CONNECTION)); - _wificounter = WIFI_CHECK_SEC; - WIFI_check_ip(); + if (wifi_counter <= 0) { + AddLog_P(LOG_LEVEL_DEBUG_MORE, S_LOG_WIFI, PSTR(D_CHECKING_CONNECTION)); + wifi_counter = WIFI_CHECK_SEC; + WifiCheckIp(); } - if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0) && !_wificonfigflag) { + if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0) && !wifi_config_type) { #ifdef USE_DISCOVERY - if (!mDNSbegun) { - mDNSbegun = MDNS.begin(Hostname); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MDNS "%s"), (mDNSbegun) ? D_INITIALIZED : D_FAILED); - addLog(LOG_LEVEL_INFO); + 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); } #endif // USE_DISCOVERY #ifdef USE_WEBSERVER - if (sysCfg.webserver) { - startWebserver(sysCfg.webserver, WiFi.localIP()); + if (Settings.webserver) { + StartWebserver(Settings.webserver, WiFi.localIP()); #ifdef USE_DISCOVERY #ifdef WEBSERVER_ADVERTISE MDNS.addService("http", "tcp", 80); #endif // WEBSERVER_ADVERTISE #endif // USE_DISCOVERY } else { - stopWebserver(); + StopWebserver(); } #ifdef USE_EMULATION - if (sysCfg.flag.emulation) { - UDP_Connect(); + if (Settings.flag.emulation) { + UdpConnect(); } #endif // USE_EMULATION #endif // USE_WEBSERVER } else { #ifdef USE_EMULATION - UDP_Disconnect(); + UdpDisconnect(); #endif // USE_EMULATION - mDNSbegun = false; + mdns_begun = false; } } } } -int WIFI_State() +int WifiState() { int state; if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { state = WIFI_RESTART; } - if (_wificonfigflag) { - state = _wificonfigflag; + if (wifi_config_type) { + state = wifi_config_type; } return state; } -void WIFI_Connect() +void WifiConnect() { WiFi.persistent(false); // Solve possible wifi init errors - _wifistatus = 0; - _wifiretry = WIFI_RETRY_SEC; - _wificounter = 1; + wifi_status = 0; + wifi_retry = WIFI_RETRY_SEC; + wifi_counter = 1; } #ifdef USE_DISCOVERY @@ -668,47 +671,30 @@ void WIFI_Connect() \*********************************************************************************************/ #ifdef MQTT_HOST_DISCOVERY -boolean mdns_discoverMQTTServer() +boolean MdnsDiscoverMqttServer() { - char ip_str[20]; - int n; - - if (!mDNSbegun) { + if (!mdns_begun) { return false; } - n = MDNS.queryService("mqtt", "tcp"); // Search for mqtt service + 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); + AddLog(LOG_LEVEL_INFO); if (n > 0) { // Note: current strategy is to get the first MQTT service (even when many are found) - IPtoCharArray(MDNS.IP(0), ip_str, 20); + 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(), ip_str, MDNS.port(0)); - addLog(LOG_LEVEL_INFO); - - strlcpy(sysCfg.mqtt_host, ip_str, sizeof(sysCfg.mqtt_host)); - sysCfg.mqtt_port = MDNS.port(0); + MDNS.hostname(0).c_str(), Settings.mqtt_host, Settings.mqtt_port); + AddLog(LOG_LEVEL_INFO); } return n > 0; } #endif // MQTT_HOST_DISCOVERY - -void IPtoCharArray(IPAddress address, char *ip_str, size_t size) -{ - String str = String(address[0]); - str += "."; - str += String(address[1]); - str += "."; - str += String(address[2]); - str += "."; - str += String(address[3]); - str.toCharArray(ip_str, size); -} #endif // USE_DISCOVERY /*********************************************************************************************\ @@ -718,7 +704,7 @@ void IPtoCharArray(IPAddress address, char *ip_str, size_t size) #ifdef USE_I2C #define I2C_RETRY_COUNTER 3 -int32_t i2c_read(uint8_t addr, uint8_t reg, uint8_t size) +int32_t I2cRead(uint8_t addr, uint8_t reg, uint8_t size) { byte x = 0; int32_t data = 0; @@ -729,7 +715,7 @@ int32_t i2c_read(uint8_t addr, uint8_t reg, uint8_t size) if (0 == Wire.endTransmission(false)) { // Try to become I2C Master, send data and collect bytes, keep master status for next request... Wire.requestFrom((int)addr, (int)size); // send data n-bytes read if (Wire.available() == size) { - for(byte i = 0; i < size; i++) { + for (byte i = 0; i < size; i++) { data <<= 8; data |= Wire.read(); // receive DATA } @@ -740,38 +726,38 @@ int32_t i2c_read(uint8_t addr, uint8_t reg, uint8_t size) return data; } -uint8_t i2c_read8(uint8_t addr, uint8_t reg) +uint8_t I2cRead8(uint8_t addr, uint8_t reg) { - return i2c_read(addr, reg, 1); + return I2cRead(addr, reg, 1); } -uint16_t i2c_read16(uint8_t addr, uint8_t reg) +uint16_t I2cRead16(uint8_t addr, uint8_t reg) { - return i2c_read(addr, reg, 2); + return I2cRead(addr, reg, 2); } -int16_t i2c_readS16(uint8_t addr, uint8_t reg) +int16_t I2cReadS16(uint8_t addr, uint8_t reg) { - return (int16_t)i2c_read(addr, reg, 2); + return (int16_t)I2cRead(addr, reg, 2); } -uint16_t i2c_read16_LE(uint8_t addr, uint8_t reg) +uint16_t I2cRead16LE(uint8_t addr, uint8_t reg) { - uint16_t temp = i2c_read(addr, reg, 2); + uint16_t temp = I2cRead(addr, reg, 2); return (temp >> 8) | (temp << 8); } -int16_t i2c_readS16_LE(uint8_t addr, uint8_t reg) +int16_t I2cReadS16_LE(uint8_t addr, uint8_t reg) { - return (int16_t)i2c_read16_LE(addr, reg); + return (int16_t)I2cRead16LE(addr, reg); } -int32_t i2c_read24(uint8_t addr, uint8_t reg) +int32_t I2cRead24(uint8_t addr, uint8_t reg) { - return i2c_read(addr, reg, 3); + return I2cRead(addr, reg, 3); } -void i2c_write8(uint8_t addr, uint8_t reg, uint8_t val) +void I2cWrite8(uint8_t addr, uint8_t reg, uint8_t val) { byte x = I2C_RETRY_COUNTER; @@ -783,14 +769,14 @@ void i2c_write8(uint8_t addr, uint8_t reg, uint8_t val) } while (Wire.endTransmission(true) != 0 && x != 0); // end transmission } -void i2c_scan(char *devs, unsigned int devs_len) +void I2cScan(char *devs, unsigned int devs_len) { byte error; byte address; byte any = 0; char tstr[10]; - snprintf_P(devs, devs_len, PSTR("{\"I2Cscan\":\"Device(s) found at")); + snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_I2CSCAN_DEVICES_FOUND_AT)); for (address = 1; address <= 127; address++) { Wire.beginTransmission(address); error = Wire.endTransmission(); @@ -800,15 +786,26 @@ void i2c_scan(char *devs, unsigned int devs_len) any = 1; } else if (4 == error) { - snprintf_P(devs, devs_len, PSTR("{\"I2Cscan\":\"Unknown error at 0x%2x\"}"), address); + snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_I2CSCAN_UNKNOWN_ERROR_AT " 0x%2x\"}"), address); } } if (any) { strncat(devs, "\"}", devs_len); } else { - snprintf_P(devs, devs_len, PSTR("{\"I2Cscan\":\"No devices found\"}")); + snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_I2CSCAN_NO_DEVICES_FOUND "\"}")); } } + +boolean I2cDevice(byte addr) +{ + for (byte address = 1; address <= 127; address++) { + Wire.beginTransmission(address); + if (!Wire.endTransmission() && (address == addr)) { + return true; + } + } + return false; +} #endif // USE_I2C /*********************************************************************************************\ @@ -827,19 +824,19 @@ extern "C" { #define SECS_PER_DAY ((uint32_t)(SECS_PER_HOUR * 24UL)) #define LEAP_YEAR(Y) (((1970+Y)>0) && !((1970+Y)%4) && (((1970+Y)%100) || !((1970+Y)%400))) -Ticker tickerRTC; +Ticker TickerRtc; -static const uint8_t monthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; // API starts months from 1, this array starts from 0 +static const uint8_t kDaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; // API starts months from 1, this array starts from 0 -uint32_t utctime = 0; -uint32_t loctime = 0; -uint32_t dsttime = 0; -uint32_t stdtime = 0; -uint32_t ntptime = 0; +uint32_t utc_time = 0; +uint32_t local_time = 0; +uint32_t daylight_saving_time = 0; +uint32_t standard_time = 0; +uint32_t ntp_time = 0; uint32_t midnight = 1451602800; -uint8_t midnightnow = 0; +uint8_t midnight_now = 0; -String getBuildDateTime() +String GetBuildDateAndTime() { // "2017-03-07T11:08:02" - ISO8601:2004 char bdt[21]; @@ -865,94 +862,94 @@ String getBuildDateTime() year = atoi(str); } } - month = (strstr(monthNames, smonth) -monthNames) /3 +1; + month = (strstr(kMonthNames, smonth) -kMonthNames) /3 +1; snprintf_P(bdt, sizeof(bdt), PSTR("%d" D_YEAR_MONTH_SEPARATOR "%02d" D_MONTH_DAY_SEPARATOR "%02d" D_DATE_TIME_SEPARATOR "%s"), year, month, day, __TIME__); return String(bdt); } -String getDateTime() +String GetDateAndTime() { // "2017-03-07T11:08:02" - ISO8601:2004 char dt[21]; snprintf_P(dt, sizeof(dt), PSTR("%04d" D_YEAR_MONTH_SEPARATOR "%02d" D_MONTH_DAY_SEPARATOR "%02d" D_DATE_TIME_SEPARATOR "%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), - rtcTime.Year, rtcTime.Month, rtcTime.Day, rtcTime.Hour, rtcTime.Minute, rtcTime.Second); + RtcTime.year, RtcTime.month, RtcTime.day_of_month, RtcTime.hour, RtcTime.minute, RtcTime.second); return String(dt); } -String getUTCDateTime() +String GetUtcDateAndTime() { // "2017-03-07T11:08:02" - ISO8601:2004 char dt[21]; TIME_T tmpTime; - breakTime(utctime, tmpTime); - tmpTime.Year += 1970; + BreakTime(utc_time, tmpTime); + tmpTime.year += 1970; snprintf_P(dt, sizeof(dt), PSTR("%04d" D_YEAR_MONTH_SEPARATOR "%02d" D_MONTH_DAY_SEPARATOR "%02d" D_DATE_TIME_SEPARATOR "%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), - tmpTime.Year, tmpTime.Month, tmpTime.Day, tmpTime.Hour, tmpTime.Minute, tmpTime.Second); + tmpTime.year, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second); return String(dt); } -void breakTime(uint32_t timeInput, TIME_T &tm) +void BreakTime(uint32_t time_input, TIME_T &tm) { -// break the given timeInput into time components +// break the given time_input into time components // this is a more compact version of the C library localtime function // note that year is offset from 1970 !!! uint8_t year; uint8_t month; - uint8_t monthLength; + uint8_t month_length; uint32_t time; unsigned long days; - time = timeInput; - tm.Second = time % 60; + time = time_input; + tm.second = time % 60; time /= 60; // now it is minutes - tm.Minute = time % 60; + tm.minute = time % 60; time /= 60; // now it is hours - tm.Hour = time % 24; + tm.hour = time % 24; time /= 24; // now it is days - tm.Wday = ((time + 4) % 7) + 1; // Sunday is day 1 + tm.day_of_week = ((time + 4) % 7) + 1; // Sunday is day 1 year = 0; days = 0; while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) { year++; } - tm.Year = year; // year is offset from 1970 + tm.year = year; // year is offset from 1970 days -= LEAP_YEAR(year) ? 366 : 365; time -= days; // now it is days in this year, starting at 0 - tm.DayOfYear = time; + tm.day_of_year = time; days = 0; month = 0; - monthLength = 0; + month_length = 0; for (month = 0; month < 12; month++) { if (1 == month) { // february if (LEAP_YEAR(year)) { - monthLength = 29; + month_length = 29; } else { - monthLength = 28; + month_length = 28; } } else { - monthLength = monthDays[month]; + month_length = kDaysInMonth[month]; } - if (time >= monthLength) { - time -= monthLength; + if (time >= month_length) { + time -= month_length; } else { break; } } - strlcpy(tm.MonthName, monthNames + (month *3), 4); - tm.Month = month + 1; // jan is month 1 - tm.Day = time + 1; // day of month - tm.Valid = (timeInput > 1451602800); // 2016-01-01 + strlcpy(tm.name_of_month, kMonthNames + (month *3), 4); + tm.month = month + 1; // jan is month 1 + tm.day_of_month = time + 1; // day of month + tm.valid = (time_input > 1451602800); // 2016-01-01 } -uint32_t makeTime(TIME_T &tm) +uint32_t MakeTime(TIME_T &tm) { // assemble time elements into time_t // note year argument is offset from 1970 @@ -961,29 +958,29 @@ uint32_t makeTime(TIME_T &tm) uint32_t seconds; // seconds from 1970 till 1 jan 00:00:00 of the given year - seconds = tm.Year * (SECS_PER_DAY * 365); - for (i = 0; i < tm.Year; i++) { + seconds = tm.year * (SECS_PER_DAY * 365); + for (i = 0; i < tm.year; i++) { if (LEAP_YEAR(i)) { seconds += SECS_PER_DAY; // add extra days for leap years } } // add days for this year, months start from 1 - for (i = 1; i < tm.Month; i++) { - if ((2 == i) && LEAP_YEAR(tm.Year)) { + for (i = 1; i < tm.month; i++) { + if ((2 == i) && LEAP_YEAR(tm.year)) { seconds += SECS_PER_DAY * 29; } else { - seconds += SECS_PER_DAY * monthDays[i-1]; // monthDay array starts from 0 + seconds += SECS_PER_DAY * kDaysInMonth[i-1]; // monthDay array starts from 0 } } - seconds+= (tm.Day - 1) * SECS_PER_DAY; - seconds+= tm.Hour * SECS_PER_HOUR; - seconds+= tm.Minute * SECS_PER_MIN; - seconds+= tm.Second; + seconds+= (tm.day_of_month - 1) * SECS_PER_DAY; + seconds+= tm.hour * SECS_PER_HOUR; + seconds+= tm.minute * SECS_PER_MIN; + seconds+= tm.second; return seconds; } -uint32_t toTime_t(TimeChangeRule r, int yr) +uint32_t RuleToTime(TimeChangeRule r, int yr) { TIME_T tm; uint32_t t; @@ -1000,53 +997,53 @@ uint32_t toTime_t(TimeChangeRule r, int yr) w = 1; // and treat as first week of next month, subtract 7 days later } - tm.Hour = r.hour; - tm.Minute = 0; - tm.Second = 0; - tm.Day = 1; - tm.Month = m; - tm.Year = yr - 1970; - t = makeTime(tm); // First day of the month, or first day of next month for "Last" rules - breakTime(t, tm); - t += (7 * (w - 1) + (r.dow - tm.Wday + 7) % 7) * SECS_PER_DAY; + tm.hour = r.hour; + tm.minute = 0; + tm.second = 0; + tm.day_of_month = 1; + tm.month = m; + tm.year = yr - 1970; + t = MakeTime(tm); // First day of the month, or first day of next month for "Last" rules + BreakTime(t, tm); + t += (7 * (w - 1) + (r.dow - tm.day_of_week + 7) % 7) * SECS_PER_DAY; if (0 == r.week) { t -= 7 * SECS_PER_DAY; //back up a week if this is a "Last" rule } return t; } -String rtc_time(int type) +String GetTime(int type) { char stime[25]; // Skip newline - uint32_t time = utctime; - if (1 == type) time = loctime; - if (2 == type) time = dsttime; - if (3 == type) time = stdtime; + uint32_t time = utc_time; + if (1 == type) time = local_time; + if (2 == type) time = daylight_saving_time; + if (3 == type) time = standard_time; snprintf_P(stime, sizeof(stime), sntp_get_real_time(time)); return String(stime); } -uint32_t rtc_loctime() +uint32_t LocalTime() { - return loctime; + return local_time; } -uint32_t rtc_midnight() +uint32_t Midnight() { return midnight; } -boolean rtc_midnight_now() +boolean MidnightNow() { - boolean mnflg = midnightnow; + boolean mnflg = midnight_now; if (mnflg) { - midnightnow = 0; + midnight_now = 0; } return mnflg; } -void rtc_second() +void RtcSecond() { byte ntpsync; uint32_t stdoffset; @@ -1054,87 +1051,92 @@ void rtc_second() TIME_T tmpTime; ntpsync = 0; - if (rtcTime.Year < 2016) { + if (RtcTime.year < 2016) { if (WL_CONNECTED == WiFi.status()) { ntpsync = 1; // Initial NTP sync } } else { - if ((1 == rtcTime.Minute) && (1 == rtcTime.Second)) { + if ((1 == RtcTime.minute) && (1 == RtcTime.second)) { ntpsync = 1; // Hourly NTP sync at xx:01:01 } } if (ntpsync) { - ntptime = sntp_get_current_timestamp(); - if (ntptime) { - utctime = ntptime; - breakTime(utctime, tmpTime); - rtcTime.Year = tmpTime.Year + 1970; - dsttime = toTime_t(myDST, rtcTime.Year); - stdtime = toTime_t(mySTD, rtcTime.Year); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "(" D_UTC_TIME ") %s"), rtc_time(0).c_str()); - addLog(LOG_LEVEL_DEBUG); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "(" D_DST_TIME ") %s"), rtc_time(2).c_str()); - addLog(LOG_LEVEL_DEBUG); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "(" D_STD_TIME ") %s"), rtc_time(3).c_str()); - addLog(LOG_LEVEL_DEBUG); + ntp_time = sntp_get_current_timestamp(); + if (ntp_time) { + utc_time = ntp_time; + BreakTime(utc_time, tmpTime); + RtcTime.year = tmpTime.year + 1970; + daylight_saving_time = RuleToTime(DaylightSavingTime, RtcTime.year); + standard_time = RuleToTime(StandardTime, RtcTime.year); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "(" D_UTC_TIME ") %s"), GetTime(0).c_str()); + AddLog(LOG_LEVEL_DEBUG); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "(" D_DST_TIME ") %s"), GetTime(2).c_str()); + AddLog(LOG_LEVEL_DEBUG); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "(" D_STD_TIME ") %s"), GetTime(3).c_str()); + AddLog(LOG_LEVEL_DEBUG); } } - utctime++; - loctime = utctime; - if (loctime > 1451602800) { // 2016-01-01 - if (99 == sysCfg.timezone) { - dstoffset = myDST.offset * SECS_PER_MIN; - stdoffset = mySTD.offset * SECS_PER_MIN; - if ((utctime >= (dsttime - stdoffset)) && (utctime < (stdtime - dstoffset))) { - loctime += dstoffset; // Daylight Saving Time + utc_time++; + local_time = utc_time; + if (local_time > 1451602800) { // 2016-01-01 + if (99 == Settings.timezone) { + if (DaylightSavingTime.hemis) { + dstoffset = StandardTime.offset * SECS_PER_MIN; // Southern hemisphere + stdoffset = DaylightSavingTime.offset * SECS_PER_MIN; } else { - loctime += stdoffset; // Standard Time + dstoffset = DaylightSavingTime.offset * SECS_PER_MIN; // Northern hemisphere + stdoffset = StandardTime.offset * SECS_PER_MIN; + } + if ((utc_time >= (daylight_saving_time - stdoffset)) && (utc_time < (standard_time - dstoffset))) { + local_time += dstoffset; // Daylight Saving Time + } else { + local_time += stdoffset; // Standard Time } } else { - loctime += sysCfg.timezone * SECS_PER_HOUR; + local_time += Settings.timezone * SECS_PER_HOUR; } } - breakTime(loctime, rtcTime); - if (!rtcTime.Hour && !rtcTime.Minute && !rtcTime.Second && rtcTime.Valid) { - midnight = loctime; - midnightnow = 1; + BreakTime(local_time, RtcTime); + if (!RtcTime.hour && !RtcTime.minute && !RtcTime.second && RtcTime.valid) { + midnight = local_time; + midnight_now = 1; } - rtcTime.Year += 1970; + RtcTime.year += 1970; } -void rtc_init() +void RtcInit() { - sntp_setservername(0, sysCfg.ntp_server[0]); - sntp_setservername(1, sysCfg.ntp_server[1]); - sntp_setservername(2, sysCfg.ntp_server[2]); + sntp_setservername(0, Settings.ntp_server[0]); + sntp_setservername(1, Settings.ntp_server[1]); + sntp_setservername(2, Settings.ntp_server[2]); sntp_stop(); sntp_set_timezone(0); // UTC time sntp_init(); - utctime = 0; - breakTime(utctime, rtcTime); - tickerRTC.attach(1, rtc_second); + utc_time = 0; + BreakTime(utc_time, RtcTime); + TickerRtc.attach(1, RtcSecond); } /*********************************************************************************************\ * Miscellaneous \*********************************************************************************************/ -float convertTemp(float c) +float ConvertTemp(float c) { float result = c; - if (!isnan(c) && sysCfg.flag.temperature_conversion) { + if (!isnan(c) && Settings.flag.temperature_conversion) { result = c * 1.8 + 32; // Fahrenheit } return result; } -char tempUnit() +char TempUnit() { - return (sysCfg.flag.temperature_conversion) ? 'F' : 'C'; + return (Settings.flag.temperature_conversion) ? 'F' : 'C'; } -uint16_t getAdc0() +uint16_t GetAdc0() { uint16_t alr = 0; for (byte i = 0; i < 32; i++) { @@ -1144,67 +1146,158 @@ uint16_t getAdc0() return alr >> 5; } +double FastPrecisePow(double a, double b) +{ + // https://martin.ankerl.com/2012/01/25/optimized-approximative-pow-in-c-and-cpp/ + // calculate approximation with fraction of the exponent + int e = (int)b; + union { + double d; + int x[2]; + } u = { a }; + u.x[1] = (int)((b - e) * (u.x[1] - 1072632447) + 1072632447); + u.x[0] = 0; + // exponentiation by squaring with the exponent's integer part + // double r = u.d makes everything much slower, not sure why + double r = 1.0; + while (e) { + if (e & 1) { + r *= a; + } + a *= a; + e >>= 1; + } + return r * u.d; +} + +char* GetTextIndexed(char* destination, size_t destination_size, uint16_t index, const char* haystack) +{ + // Returns empty string if not found + // Returns text of found + char* write = destination; + const char* read = haystack; + + index++; + while (index--) { + size_t size = destination_size -1; + write = destination; + char ch = '.'; + while ((ch != '\0') && (ch != '|')) { + ch = pgm_read_byte(read++); + if (size && (ch != '|')) { + *write++ = ch; + size--; + } + } + if (0 == ch) { + if (index) { + write = destination; + } + break; + } + } + *write = '\0'; + return destination; +} + +int GetCommandCode(char* destination, size_t destination_size, const char* needle, const char* haystack) +{ + // Returns -1 of not found + // Returns index and command if found + int result = -1; + const char* read = haystack; + char* write = destination; + size_t maxcopy = (strlen(needle) > destination_size) ? destination_size : strlen(needle); + + while (true) { + result++; + size_t size = destination_size -1; + write = destination; + char ch = '.'; + while ((ch != '\0') && (ch != '|')) { + ch = pgm_read_byte(read++); + if (size && (ch != '|')) { + *write++ = ch; + size--; + } + } + *write = '\0'; + if (!strcasecmp(needle, destination)) { + break; + } + if (0 == ch) { + result = -1; + break; + } + } + return result; +} + /*********************************************************************************************\ * Syslog \*********************************************************************************************/ -void syslog() +void Syslog() { // Destroys log_data char syslog_preamble[64]; // Hostname + Id - if (portUDP.beginPacket(sysCfg.syslog_host, sysCfg.syslog_port)) { - snprintf_P(syslog_preamble, sizeof(syslog_preamble), PSTR("%s ESP-"), Hostname); + if ((static_cast(syslog_host_addr) == 0) || ((millis() - syslog_host_refresh) > 60000)) { + WiFi.hostByName(Settings.syslog_host, syslog_host_addr); + syslog_host_refresh = millis(); + } + if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { + snprintf_P(syslog_preamble, sizeof(syslog_preamble), PSTR("%s ESP-"), my_hostname); memmove(log_data + strlen(syslog_preamble), log_data, sizeof(log_data) - strlen(syslog_preamble)); log_data[sizeof(log_data) -1] = '\0'; memcpy(log_data, syslog_preamble, strlen(syslog_preamble)); - portUDP.write(log_data); - portUDP.endPacket(); + PortUdp.write(log_data); + PortUdp.endPacket(); } else { syslog_level = 0; syslog_timer = SYSLOG_TIMER; snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_SYSLOG_HOST_NOT_FOUND ". " D_RETRY_IN " %d " D_UNIT_SECOND), SYSLOG_TIMER); - addLog(LOG_LEVEL_INFO); + AddLog(LOG_LEVEL_INFO); } } -void addLog(byte loglevel) +void AddLog(byte loglevel) { char mxtime[9]; // 13:45:21 - snprintf_P(mxtime, sizeof(mxtime), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), rtcTime.Hour, rtcTime.Minute, rtcTime.Second); + snprintf_P(mxtime, sizeof(mxtime), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); if (loglevel <= seriallog_level) { Serial.printf("%s %s\n", mxtime, log_data); } #ifdef USE_WEBSERVER - if (sysCfg.webserver && (loglevel <= sysCfg.weblog_level)) { - Log[logidx] = String(mxtime) + " " + String(log_data); - logidx++; - if (logidx > MAX_LOG_LINES -1) { - logidx = 0; + if (Settings.webserver && (loglevel <= Settings.weblog_level)) { + web_log[web_log_index] = String(mxtime) + " " + String(log_data); + web_log_index++; + if (web_log_index > MAX_LOG_LINES -1) { + web_log_index = 0; } } #endif // USE_WEBSERVER if ((WL_CONNECTED == WiFi.status()) && (loglevel <= syslog_level)) { - syslog(); + Syslog(); } } -void addLog_P(byte loglevel, const char *formatP) +void AddLog_P(byte loglevel, const char *formatP) { snprintf_P(log_data, sizeof(log_data), formatP); - addLog(loglevel); + AddLog(loglevel); } -void addLog_P(byte loglevel, const char *formatP, const char *formatP2) +void AddLog_P(byte loglevel, const char *formatP, const char *formatP2) { char message[100]; snprintf_P(log_data, sizeof(log_data), formatP); snprintf_P(message, sizeof(message), formatP2); strncat(log_data, message, sizeof(log_data)); - addLog(loglevel); + AddLog(loglevel); } /*********************************************************************************************\ diff --git a/sonoff/user_config.h b/sonoff/user_config.h index d614e7593..671b07cea 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -17,6 +17,9 @@ along with this program. If not, see . */ +#ifndef _USER_CONFIG_H_ +#define _USER_CONFIG_H_ + /*********************************************************************************************\ * ATTENTION: Changes to most PARAMETER defines will only override flash settings if you change * define CFG_HOLDER. @@ -26,8 +29,10 @@ \*********************************************************************************************/ // -- Localization -------------------------------- -//#define MY_LANGUAGE en-GB // Enabled by Default -//#define MY_LANGUAGE nl-NL +//#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 // -- Project ------------------------------------- #define PROJECT "sonoff" // PROJECT is used as the default topic delimiter and OTA file name @@ -39,7 +44,7 @@ // -- Wifi ---------------------------------------- #define WIFI_IP_ADDRESS "0.0.0.0" // [IpAddress1] Set to 0.0.0.0 for using DHCP or IP address -#define WIFI_GATEWAY "192.168.2.254" // {IpAddress2] If not using DHCP set Gateway IP address +#define WIFI_GATEWAY "192.168.2.254" // [IpAddress2] If not using DHCP set Gateway IP address #define WIFI_SUBNETMASK "255.255.255.0" // [IpAddress3] If not using DHCP set Network mask #define WIFI_DNS "192.168.2.27" // [IpAddress4] If not using DHCP set DNS IP address (might be equal to WIFI_GATEWAY) @@ -105,13 +110,13 @@ #define TELE_PERIOD 300 // [TelePeriod] Telemetry (0 = disable, 10 - 3600 seconds) // -- MQTT - Domoticz ----------------------------- -#define USE_DOMOTICZ // Enable Domoticz (+7k code, +0.3k mem) - Disable by // +#define USE_DOMOTICZ // Enable Domoticz (+6k code, +0.3k mem) - Disable by // #define DOMOTICZ_IN_TOPIC "domoticz/in" // Domoticz Input Topic #define DOMOTICZ_OUT_TOPIC "domoticz/out" // Domoticz Output Topic #define DOMOTICZ_UPDATE_TIMER 0 // [DomoticzUpdateTimer] Send relay status (0 = disable, 1 - 3600 seconds) (Optional) // -- HTTP ---------------------------------------- -#define USE_WEBSERVER // Enable web server and wifi manager (+62k code, +8k mem) - Disable by // +#define USE_WEBSERVER // Enable web server and wifi manager (+66k code, +8k mem) - Disable by // #define WEB_SERVER 2 // [WebServer] Web server (0 = Off, 1 = Start as User, 2 = Start as Admin) #define WEB_PORT 80 // Web server Port for User and Admin mode #define WEB_USERNAME "admin" // Web server Admin mode user name @@ -131,10 +136,10 @@ #define NTP_SERVER3 "0.nl.pool.ntp.org" // [NtpServer3] Select third NTP server by name or IP address (93.94.224.67) // -- Time - Start Daylight Saving Time and timezone offset from UTC in minutes -#define TIME_DST Last, Sun, Mar, 2, +120 // Last sunday in march at 02:00 +120 minutes +#define TIME_DST North, Last, Sun, Mar, 2, +120 // Northern Hemisphere, Last sunday in march at 02:00 +120 minutes // -- Time - Start Standard Time and timezone offset from UTC in minutes -#define TIME_STD Last, Sun, Oct, 3, +60 // Last sunday in october 02:00 +60 minutes +#define TIME_STD North, Last, Sun, Oct, 3, +60 // Northern Hemisphere, Last sunday in october 02:00 +60 minutes // -- Application --------------------------------- #define APP_TIMEZONE 1 // [Timezone] +1 hour (Amsterdam) (-12 .. 12 = hours from UTC, 99 = use TIME_DST/TIME_STD) @@ -162,17 +167,18 @@ #define USE_I2C // I2C using library wire (+10k code, 0.2k mem) - Disable by // #define USE_BH1750 // Add I2C code for BH1750 sensor +// #define USE_VEML6070 // Add I2C code for VEML6070 sensor (+0.5k code) #define USE_BMP // Add I2C code for BMP/BME280 sensor #define USE_HTU // Add I2C code for HTU21/SI7013/SI7020/SI7021 sensor #define USE_SHT // Add I2C emulating code for SHT1X sensor #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+3k code, 0.3k mem) // #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) + #define USE_IR_RECEIVE // Support for IR receiver (+4k code) #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem) - Disable by // #define USE_WS2812_CTYPE 1 // WS2812 Color type (0 - RGB, 1 - GRB) -// #define USE_WS2812_DMA // DMA supports only GPIO03 (= Serial RXD) (+1k mem) - // When USE_WS2812_DMA is enabled expect Exceptions on Pow +// #define USE_WS2812_DMA // DMA supports only GPIO03 (= Serial RXD) (+1k mem). When USE_WS2812_DMA is enabled expect Exceptions on Pow /*********************************************************************************************\ * Compile a minimal version if upgrade memory gets tight ONLY TO BE USED FOR UPGRADE STEP 1! @@ -191,7 +197,4 @@ #error "Select either USE_MQTT_TLS or USE_WEBSERVER as there is just not enough memory to play with" #endif -#if (ARDUINO < 10610) - #error "This software is supported with Arduino IDE starting from 1.6.10 and ESP8266 Release 2.3.0" -#endif - +#endif // _USER_CONFIG_H_ diff --git a/sonoff/user_config_override.h b/sonoff/user_config_override.h index 02631af99..37fe10e6c 100644 --- a/sonoff/user_config_override.h +++ b/sonoff/user_config_override.h @@ -17,6 +17,9 @@ along with this program. If not, see . */ +#ifndef _USER_CONFIG_OVERRIDE_H_ +#define _USER_CONFIG_OVERRIDE_H_ + /*****************************************************************************************************\ * ATTENTION: - Changes to most PARAMETER defines will only override flash settings if you change * define CFG_HOLDER. @@ -38,3 +41,4 @@ //#endif //#define STA_SSID1 "yourssid1" +#endif // _USER_CONFIG_OVERRIDE_H_ \ No newline at end of file diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index 1873cd6bc..d8f6dbfb9 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -77,7 +77,7 @@ const char HTTP_HEAD[] PROGMEM = ""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - snprintf_P(stopic, sizeof(stopic), PSTR(" at %X"), CFG_Address()); - page += F(""); - page += F(""); - page += F(""); - for (byte i = 0; i < Maxdevice; i++) { - page += F(""); + page += F("
"); + + // Save 1k of code space replacing table html with javascript replace codes + // }1 =
" D_PROGRAM_VERSION ""); page += Version; page += F("
" D_BUILD_DATE_AND_TIME ""); page += getBuildDateTime(); page += F("
" D_CORE_AND_SDK_VERSION ""); page += ESP.getCoreVersion(); page += F("/"); page += String(ESP.getSdkVersion()); page += F("
" D_UPTIME ""); page += String(uptime); page += F(" Hours
" D_FLASH_WRITE_COUNT ""); page += String(sysCfg.saveFlag); page += stopic; page += F("
" D_BOOT_COUNT ""); page += String(sysCfg.bootcount); page += F("
" D_RESTART_REASON ""); page += getResetReason(); page += F("
" D_FRIENDLY_NAME " "); - page += i +1; - page += F(""); page += sysCfg.friendlyname[i]; page += F("
+ // }2 = + String func = FPSTR(HTTP_SCRIPT_INFO_BEGIN); + func += F(""); - page += F(""); - page += F(""); + + func += F("}1}2 "); // Empty line + 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 (static_cast(WiFi.localIP()) != 0) { - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); + func += F("}1" D_IP_ADDRESS "}2"); func += WiFi.localIP().toString(); + func += F("}1" D_GATEWAY "}2"); func += IPAddress(Settings.ip_address[1]).toString(); + func += F("}1" D_SUBNET_MASK "}2"); func += IPAddress(Settings.ip_address[2]).toString(); + func += F("}1" D_DNS_SERVER "}2"); func += IPAddress(Settings.ip_address[3]).toString(); + func += F("}1" D_MAC_ADDRESS "}2"); func += WiFi.macAddress(); } if (static_cast(WiFi.softAPIP()) != 0) { - page += F(""); - page += F(""); - page += F(""); + func += F("}1" D_AP " " D_IP_ADDRESS "}2"); func += WiFi.softAPIP().toString(); + func += F("}1" D_AP " " D_GATEWAY "}2"); func += WiFi.softAPIP().toString(); + func += F("}1" D_AP " " D_MAC_ADDRESS "}2"); func += WiFi.softAPmacAddress(); } - page += F(""); - if (sysCfg.flag.mqtt_enabled) { - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - getTopic_P(stopic, 0, sysCfg.mqtt_topic, ""); - page += F(""); + + func += F("}1}2 "); // Empty line + if (Settings.flag.mqtt_enabled) { + func += F("}1" D_MQTT_HOST "}2"); func += Settings.mqtt_host; + func += F("}1" D_MQTT_PORT "}2"); func += String(Settings.mqtt_port); + func += F("}1" D_MQTT_CLIENT " &
 " D_FALLBACK_TOPIC "}2"); func += mqtt_client; + func += F("}1" D_MQTT_USER "}2"); func += Settings.mqtt_user; + func += F("}1" D_MQTT_TOPIC "}2"); func += Settings.mqtt_topic; + func += F("}1" D_MQTT_GROUP_TOPIC "}2"); func += Settings.mqtt_grptopic; + GetTopic_P(stopic, 0, Settings.mqtt_topic, ""); + func += F("}1" D_MQTT_FULL_TOPIC "}2"); func += stopic; } else { - page += F(""); + func += F("}1" D_MQTT "}2" D_DISABLED); } - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F("
"); + func += F(D_PROGRAM_VERSION "}2"); func += version; + func += F("}1" D_BUILD_DATE_AND_TIME "}2"); func += GetBuildDateAndTime(); + func += F("}1" D_CORE_AND_SDK_VERSION "}2"); func += ESP.getCoreVersion(); func += F("/"); func += String(ESP.getSdkVersion()); + func += F("}1" D_UPTIME "}2"); func += String(uptime); func += F(" Hours"); + snprintf_P(stopic, sizeof(stopic), PSTR(" at %X"), GetSettingsAddress()); + func += F("}1" D_FLASH_WRITE_COUNT "}2"); func += String(Settings.save_flag); func += stopic; + func += F("}1" D_BOOT_COUNT "}2"); func += String(Settings.bootcount); + func += F("}1" D_RESTART_REASON "}2"); func += GetResetReason(); + uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present; + for (byte i = 0; i < maxfn; i++) { + func += F("}1" D_FRIENDLY_NAME " "); func += i +1; func += F("}2"); func += Settings.friendlyname[i]; } - page += F("
 
" D_AP); page += String(sysCfg.sta_active +1); - page += F(" " D_SSID " (" D_RSSI ")"); page += sysCfg.sta_ssid[sysCfg.sta_active]; page += F(" ("); page += WIFI_getRSSIasQuality(WiFi.RSSI()); page += F("%)
" D_HOSTNAME ""); page += Hostname; page += F("
" D_IP_ADDRESS ""); page += WiFi.localIP().toString(); page += F("
" D_GATEWAY ""); page += IPAddress(sysCfg.ip_address[1]).toString(); page += F("
" D_SUBNET_MASK ""); page += IPAddress(sysCfg.ip_address[2]).toString(); page += F("
" D_DNS_SERVER ""); page += IPAddress(sysCfg.ip_address[3]).toString(); page += F("
" D_MAC_ADDRESS ""); page += WiFi.macAddress(); page += F("
" D_AP " " D_IP_ADDRESS ""); page += WiFi.softAPIP().toString(); page += F("
" D_AP " " D_GATEWAY ""); page += WiFi.softAPIP().toString(); page += F("
" D_AP " " D_MAC_ADDRESS ""); page += WiFi.softAPmacAddress(); page += F("
 
" D_MQTT_HOST ""); page += sysCfg.mqtt_host; page += F("
" D_MQTT_PORT ""); page += String(sysCfg.mqtt_port); page += F("
" D_MQTT_CLIENT " &
 " D_FALLBACK_TOPIC "
"); page += MQTTClient; page += F("
" D_MQTT_USER ""); page += sysCfg.mqtt_user; page += F("
" D_MQTT_TOPIC ""); page += sysCfg.mqtt_topic; page += F("
" D_MQTT_GROUP_TOPIC ""); page += sysCfg.mqtt_grptopic; page += F("
" D_MQTT_FULL_TOPIC ""); page += stopic; page += F("
" D_MQTT "" D_DISABLED "
 
" D_EMULATION ""); + + func += F("}1}2 "); // Empty line + func += F("}1" D_EMULATION "}2"); #ifdef USE_EMULATION - if (EMUL_WEMO == sysCfg.flag.emulation) { - page += F(D_BELKIN_WEMO); + if (EMUL_WEMO == Settings.flag.emulation) { + func += F(D_BELKIN_WEMO); } - else if (EMUL_HUE == sysCfg.flag.emulation) { - page += F(D_HUE_BRIDGE); + else if (EMUL_HUE == Settings.flag.emulation) { + func += F(D_HUE_BRIDGE); } else { - page += F(D_NONE); + func += F(D_NONE); } #else - page += F(D_DISABLED); + func += F(D_DISABLED); #endif // USE_EMULATION - page += F("
" D_MDNS_DISCOVERY ""); + func += F("}1" D_MDNS_DISCOVERY "}2"); #ifdef USE_DISCOVERY - page += F(D_ENABLED); - page += F("
" D_MDNS_ADVERTISE ""); + func += F(D_ENABLED); + func += F("}1" D_MDNS_ADVERTISE "}2"); #ifdef WEBSERVER_ADVERTISE - page += F(D_WEB_SERVER); + func += F(D_WEB_SERVER); #else - page += F(D_DISABLED); + func += F(D_DISABLED); #endif // WEBSERVER_ADVERTISE #else - page += F(D_DISABLED); + func += F(D_DISABLED); #endif // USE_DISCOVERY - page += F("
 
" D_ESP_CHIP_ID ""); page += String(ESP.getChipId()); page += F("
" D_FLASH_CHIP_ID ""); page += String(ESP.getFlashChipId()); page += F("
" D_FLASH_CHIP_SIZE ""); page += String(ESP.getFlashChipRealSize() / 1024); page += F("kB
" D_PROGRAM_FLASH_SIZE ""); page += String(ESP.getFlashChipSize() / 1024); page += F("kB
" D_PROGRAM_SIZE ""); page += String(ESP.getSketchSize() / 1024); page += F("kB
" D_FREE_PROGRAM_SPACE ""); page += String(ESP.getFreeSketchSpace() / 1024); page += F("kB
" D_FREE_MEMORY ""); page += String(freeMem / 1024); page += F("kB
"); -// page += F(""); + func += F("}1}2 "); // Empty line + func += F("}1" D_ESP_CHIP_ID "}2"); func += String(ESP.getChipId()); + func += F("}1" D_FLASH_CHIP_ID "}2"); func += String(ESP.getFlashChipId()); + func += F("}1" D_FLASH_CHIP_SIZE "}2"); func += String(ESP.getFlashChipRealSize() / 1024); func += F("kB"); + func += F("}1" D_PROGRAM_FLASH_SIZE "}2"); func += String(ESP.getFlashChipSize() / 1024); func += F("kB"); + func += F("}1" D_PROGRAM_SIZE "}2"); func += String(ESP.getSketchSize() / 1024); func += F("kB"); + func += F("}1" D_FREE_PROGRAM_SPACE "}2"); func += String(ESP.getFreeSketchSpace() / 1024); func += F("kB"); + func += F("}1" D_FREE_MEMORY "}2"); func += String(freeMem / 1024); func += F("kB"); + func += F("
"); + func += FPSTR(HTTP_SCRIPT_INFO_END); + page.replace(F(""), func); + page.replace(F(""), F("")); + + // page += F(""); page += FPSTR(HTTP_BTN_MAIN); - showPage(page); + ShowPage(page); } -void handleRestart() +void HandleRestart() { - if (httpUser()) { + if (HttpUser()) { return; } - addLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTART); + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTART); String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_RESTART)); page += FPSTR(HTTP_MSG_RSTRT); - if (HTTP_MANAGER == _httpflag) { - _httpflag = HTTP_ADMIN; + if (HTTP_MANAGER == webserver_state) { + webserver_state = HTTP_ADMIN; } else { page += FPSTR(HTTP_BTN_MAIN); } - showPage(page); + ShowPage(page); - restartflag = 2; + restart_flag = 2; } /********************************************************************************************/ -void handleNotFound() +void HandleNotFound() { - if (captivePortal()) { // If captive portal redirect instead of displaying the error page. + if (CaptivePortal()) { // If captive portal redirect instead of displaying the error page. return; } #ifdef USE_EMULATION - String path = webServer->uri(); - if ((EMUL_HUE == sysCfg.flag.emulation) && (path.startsWith("/api"))) { - handle_hue_api(&path); + String path = WebServer->uri(); + if ((EMUL_HUE == Settings.flag.emulation) && (path.startsWith("/api"))) { + HandleHueApi(&path); } else #endif // USE_EMULATION { String message = F(D_FILE_NOT_FOUND "\n\nURI: "); - message += webServer->uri(); + message += WebServer->uri(); message += F("\nMethod: "); - message += (webServer->method() == HTTP_GET) ? F("GET") : F("POST"); + message += (WebServer->method() == HTTP_GET) ? F("GET") : F("POST"); message += F("\nArguments: "); - message += webServer->args(); + message += WebServer->args(); message += F("\n"); - for ( uint8_t i = 0; i < webServer->args(); i++ ) { - message += " " + webServer->argName(i) + ": " + webServer->arg(i) + "\n"; + for ( uint8_t i = 0; i < WebServer->args(); i++ ) { + message += " " + WebServer->argName(i) + ": " + WebServer->arg(i) + "\n"; } - setHeader(); - webServer->send(404, FPSTR(HDR_CTYPE_PLAIN), message); + SetHeader(); + WebServer->send(404, FPSTR(HDR_CTYPE_PLAIN), message); } } /* Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */ -boolean captivePortal() +boolean CaptivePortal() { - if ((HTTP_MANAGER == _httpflag) && !isIp(webServer->hostHeader())) { - addLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED)); + if ((HTTP_MANAGER == webserver_state) && !ValidIpAddress(WebServer->hostHeader())) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED)); - webServer->sendHeader(F("Location"), String("http://") + webServer->client().localIP().toString(), true); - webServer->send(302, FPSTR(HDR_CTYPE_PLAIN), ""); // Empty content inhibits Content-length header so we have to close the socket ourselves. - webServer->client().stop(); // Stop is needed because we sent no content length + WebServer->sendHeader(F("Location"), String("http://") + WebServer->client().localIP().toString(), true); + WebServer->send(302, FPSTR(HDR_CTYPE_PLAIN), ""); // Empty content inhibits Content-length header so we have to close the socket ourselves. + WebServer->client().stop(); // Stop is needed because we sent no content length return true; } return false; } /** Is this an IP? */ -boolean isIp(String str) +boolean ValidIpAddress(String str) { for (uint16_t i = 0; i < str.length(); i++) { int c = str.charAt(i); diff --git a/sonoff/xdrv_domoticz.ino b/sonoff/xdrv_domoticz.ino index ffc1d5a2e..f66683f02 100644 --- a/sonoff/xdrv_domoticz.ino +++ b/sonoff/xdrv_domoticz.ino @@ -19,26 +19,31 @@ #ifdef USE_DOMOTICZ -#define DOMOTICZ_MAX_SENSORS 6 - #ifdef USE_WEBSERVER const char HTTP_FORM_DOMOTICZ[] PROGMEM = "
 " D_DOMOTICZ_PARAMETERS " 
" "" - "
"; + "
"; const char HTTP_FORM_DOMOTICZ_RELAY[] PROGMEM = - "" - ""; -const char HTTP_FORM_DOMOTICZ_SWITCH[] PROGMEM = - ""; + "" + ""; + const char HTTP_FORM_DOMOTICZ_SWITCH[] PROGMEM = + ""; const char HTTP_FORM_DOMOTICZ_SENSOR[] PROGMEM = - ""; + ""; const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM = - ""; + ""; #endif // USE_WEBSERVER -const char domoticz_sensors[DOMOTICZ_MAX_SENSORS][DOMOTICZ_SENSORS_MAX_STRING_LENGTH] PROGMEM = - { D_DOMOTICZ_TEMP, D_DOMOTICZ_TEMP_HUM, D_DOMOTICZ_TEMP_HUM_BARO, D_DOMOTICZ_POWER_ENERGY, D_DOMOTICZ_ILLUMINANCE, D_DOMOTICZ_COUNT }; +enum DomoticzCommands { + CMND_IDX, CMND_KEYIDX, CMND_SWITCHIDX, CMND_SENSORIDX, CMND_UPDATETIMER }; +const char kDomoticzCommands[] PROGMEM = + D_CMND_IDX "|" D_CMND_KEYIDX "|" D_CMND_SWITCHIDX "|" D_CMND_SENSORIDX "|" D_CMND_UPDATETIMER ; + +enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_MAX_SENSORS}; + +const char kDomoticzSensors[] PROGMEM = + D_DOMOTICZ_TEMP "|" D_DOMOTICZ_TEMP_HUM "|" D_DOMOTICZ_TEMP_HUM_BARO "|" D_DOMOTICZ_POWER_ENERGY "|" D_DOMOTICZ_ILLUMINANCE "|" D_DOMOTICZ_COUNT "|" D_DOMOTICZ_VOLTAGE "|" D_DOMOTICZ_CURRENT ; char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; char domoticz_out_topic[] = DOMOTICZ_OUT_TOPIC; @@ -47,69 +52,62 @@ boolean domoticz_subscribe = false; int domoticz_update_timer = 0; byte domoticz_update_flag = 1; -void mqtt_publishDomoticzPowerState(byte device) +void MqttPublishDomoticzPowerState(byte device) { - if (sysCfg.flag.mqtt_enabled && sysCfg.domoticz_relay_idx[device -1]) { - if ((device < 1) || (device > Maxdevice)) { - device = 1; - } - if (sfl_flg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"idx\":%d,\"nvalue\":2,\"svalue\":\"%d\"}"), - sysCfg.domoticz_relay_idx[device -1], sysCfg.led_dimmer[device -1]); - mqtt_publish(domoticz_in_topic); - } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"\"}"), - sysCfg.domoticz_relay_idx[device -1], (power & (0x01 << (device -1))) ? 1 : 0); - mqtt_publish(domoticz_in_topic); + char sdimmer[8]; + + if ((device < 1) || (device > devices_present)) { + device = 1; + } + if (Settings.flag.mqtt_enabled && Settings.domoticz_relay_idx[device -1]) { + snprintf_P(sdimmer, sizeof(sdimmer), PSTR("%d"), Settings.light_dimmer); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%s\"}"), + Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? sdimmer : ""); + MqttPublish(domoticz_in_topic); } } -void domoticz_updatePowerState(byte device) +void DomoticzUpdatePowerState(byte device) { if (domoticz_update_flag) { - mqtt_publishDomoticzPowerState(device); + MqttPublishDomoticzPowerState(device); } domoticz_update_flag = 1; } -void domoticz_mqttUpdate() +void DomoticzMqttUpdate() { - if (domoticz_subscribe && (sysCfg.domoticz_update_timer || domoticz_update_timer)) { + if (domoticz_subscribe && (Settings.domoticz_update_timer || domoticz_update_timer)) { domoticz_update_timer--; if (domoticz_update_timer <= 0) { - domoticz_update_timer = sysCfg.domoticz_update_timer; - for (byte i = 1; i <= Maxdevice; i++) { - mqtt_publishDomoticzPowerState(i); + domoticz_update_timer = Settings.domoticz_update_timer; + for (byte i = 1; i <= devices_present; i++) { + MqttPublishDomoticzPowerState(i); } } } } -void domoticz_setUpdateTimer(uint16_t value) +void DomoticzSetUpdateTimer(uint16_t value) { domoticz_update_timer = value; } -void domoticz_mqttSubscribe() +void DomoticzMqttSubscribe() { - for (byte i = 0; i < Maxdevice; i++) { - if (sysCfg.domoticz_relay_idx[i]) { + uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; + for (byte i = 0; i < maxdev; i++) { + if (Settings.domoticz_relay_idx[i]) { domoticz_subscribe = true; } } if (domoticz_subscribe) { char stopic[TOPSZ]; snprintf_P(stopic, sizeof(stopic), PSTR("%s/#"), domoticz_out_topic); // domoticz topic - mqttClient.subscribe(stopic); - mqttClient.loop(); // Solve LmacRxBlk:1 messages + MqttSubscribe(stopic); } } -boolean domoticz_update() -{ - return domoticz_update_flag; -} - /* * ArduinoJSON Domoticz Switch entry used to calculate jsonBuf: JSON_OBJECT_SIZE(11) + 129 = 313 { @@ -127,7 +125,7 @@ boolean domoticz_update() } */ -boolean domoticz_mqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t sdataBuf) +boolean DomoticzMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t sdataBuf) { char stemp1[10]; char scommand[10]; @@ -136,7 +134,7 @@ boolean domoticz_mqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uin int16_t found = 0; domoticz_update_flag = 1; - if (!strncmp(topicBuf, domoticz_out_topic, strlen(domoticz_out_topic)) != 0) { + if (!strncmp(topicBuf, domoticz_out_topic, strlen(domoticz_out_topic))) { if (sdataBuf < 20) { return 1; } @@ -152,25 +150,26 @@ boolean domoticz_mqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uin nvalue = domoticz["nvalue"]; snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue); - addLog(LOG_LEVEL_DEBUG_MORE); + AddLog(LOG_LEVEL_DEBUG_MORE); - if (nvalue >= 0 && nvalue <= 2) { - for (byte i = 0; i < Maxdevice; i++) { - if ((idx > 0) && (idx == sysCfg.domoticz_relay_idx[i])) { + if ((idx > 0) && (nvalue >= 0) && (nvalue <= 2)) { + uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; + for (byte i = 0; i < maxdev; i++) { + if (idx == Settings.domoticz_relay_idx[i]) { snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); if (2 == nvalue) { nvalue = domoticz["svalue1"]; - if (sfl_flg && (sysCfg.led_dimmer[i] == nvalue)) { + if (light_type && (Settings.light_dimmer == nvalue) && ((power >> i) &1)) { return 1; } - snprintf_P(topicBuf, stopicBuf, PSTR("/" D_CMND_DIMMER "%s"), (Maxdevice > 1) ? stemp1 : ""); + snprintf_P(topicBuf, stopicBuf, PSTR("/" D_CMND_DIMMER)); snprintf_P(dataBuf, sdataBuf, PSTR("%d"), nvalue); found = 1; } else { if (((power >> i) &1) == nvalue) { return 1; } - snprintf_P(topicBuf, stopicBuf, PSTR("/" D_CMND_POWER "%s"), (Maxdevice > 1) ? stemp1 : ""); + snprintf_P(topicBuf, stopicBuf, PSTR("/" D_CMND_POWER "%s"), (devices_present > 1) ? stemp1 : ""); snprintf_P(dataBuf, sdataBuf, PSTR("%d"), nvalue); found = 1; } @@ -183,7 +182,7 @@ boolean domoticz_mqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uin } snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DOMOTICZ D_RECEIVED_TOPIC " %s, " D_DATA " %s"), topicBuf, dataBuf); - addLog(LOG_LEVEL_DEBUG_MORE); + AddLog(LOG_LEVEL_DEBUG_MORE); domoticz_update_flag = 0; } @@ -194,42 +193,44 @@ boolean domoticz_mqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uin * Commands \*********************************************************************************************/ -boolean domoticz_command(const char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload) +boolean DomoticzCommand(const char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload) { + char command [CMDSZ]; boolean serviced = true; uint8_t dmtcz_len = strlen(D_CMND_DOMOTICZ); // Prep for string length change if (!strncasecmp_P(type, PSTR(D_CMND_DOMOTICZ), dmtcz_len)) { // Prefix - if (!strcasecmp_P(type +dmtcz_len, PSTR(D_CMND_IDX)) && (index > 0) && (index <= Maxdevice)) { + int command_code = GetCommandCode(command, sizeof(command), type +dmtcz_len, kDomoticzCommands); + if ((CMND_IDX == command_code) && (index > 0) && (index <= MAX_DOMOTICZ_IDX)) { if (payload >= 0) { - sysCfg.domoticz_relay_idx[index -1] = payload; - restartflag = 2; + Settings.domoticz_relay_idx[index -1] = payload; + restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DOMOTICZ D_CMND_IDX "%d\":%d}"), index, sysCfg.domoticz_relay_idx[index -1]); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DOMOTICZ "%s%d\":%d}"), command, index, Settings.domoticz_relay_idx[index -1]); } - else if (!strcasecmp_P(type +dmtcz_len, PSTR(D_CMND_KEYIDX)) && (index > 0) && (index <= Maxdevice)) { + else if ((CMND_KEYIDX == command_code) && (index > 0) && (index <= MAX_DOMOTICZ_IDX)) { if (payload >= 0) { - sysCfg.domoticz_key_idx[index -1] = payload; + Settings.domoticz_key_idx[index -1] = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DOMOTICZ D_CMND_KEYIDX "%d\":%d}"), index, sysCfg.domoticz_key_idx[index -1]); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DOMOTICZ "%s%d\":%d}"), command, index, Settings.domoticz_key_idx[index -1]); } - else if (!strcasecmp_P(type +dmtcz_len, PSTR(D_CMND_SWITCHIDX)) && (index > 0) && (index <= Maxdevice)) { + else if ((CMND_SWITCHIDX == command_code) && (index > 0) && (index <= MAX_DOMOTICZ_IDX)) { if (payload >= 0) { - sysCfg.domoticz_switch_idx[index -1] = payload; + Settings.domoticz_switch_idx[index -1] = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DOMOTICZ D_CMND_SWITCHIDX "%d\":%d}"), index, sysCfg.domoticz_key_idx[index -1]); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DOMOTICZ "%s%d\":%d}"), command, index, Settings.domoticz_key_idx[index -1]); } - else if (!strcasecmp_P(type +dmtcz_len, PSTR(D_CMND_SENSORIDX)) && (index > 0) && (index <= DOMOTICZ_MAX_SENSORS)) { + else if ((CMND_SENSORIDX == command_code) && (index > 0) && (index <= DZ_MAX_SENSORS)) { if (payload >= 0) { - sysCfg.domoticz_sensor_idx[index -1] = payload; + Settings.domoticz_sensor_idx[index -1] = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DOMOTICZ D_CMND_SENSORIDX "%d\":%d}"), index, sysCfg.domoticz_sensor_idx[index -1]); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DOMOTICZ "%s%d\":%d}"), command, index, Settings.domoticz_sensor_idx[index -1]); } - else if (!strcasecmp_P(type +dmtcz_len, PSTR(D_CMND_UPDATETIMER))) { + else if (CMND_UPDATETIMER == command_code) { if ((payload >= 0) && (payload < 3601)) { - sysCfg.domoticz_update_timer = payload; + Settings.domoticz_update_timer = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DOMOTICZ D_CMND_UPDATETIMER "\":%d}"), sysCfg.domoticz_update_timer); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DOMOTICZ "%s\":%d}"), command, Settings.domoticz_update_timer); } else serviced = false; } @@ -237,12 +238,12 @@ boolean domoticz_command(const char *type, uint16_t index, char *dataBuf, uint16 return serviced; } -boolean domoticz_button(byte key, byte device, byte state, byte svalflg) +boolean DomoticzButton(byte key, byte device, byte state, byte svalflg) { - if ((sysCfg.domoticz_key_idx[device -1] || sysCfg.domoticz_switch_idx[device -1]) && (svalflg)) { + if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"), - (key) ? sysCfg.domoticz_switch_idx[device -1] : sysCfg.domoticz_key_idx[device -1], (state) ? (2 == state) ? "Toggle" : "On" : "Off"); - mqtt_publish(domoticz_in_topic); + (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (2 == state) ? "Toggle" : "On" : "Off"); + MqttPublish(domoticz_in_topic); return 1; } else { return 0; @@ -253,63 +254,51 @@ boolean domoticz_button(byte key, byte device, byte state, byte svalflg) * Sensors \*********************************************************************************************/ -uint8_t dom_hum_stat(char *hum) +uint8_t DomoticzHumidityState(char *hum) { uint8_t h = atoi(hum); return (!h) ? 0 : (h < 40) ? 2 : (h > 70) ? 3 : 1; } -void dom_sensor(byte idx, char *data) +void DomoticzSensor(byte idx, char *data) { - if (sysCfg.domoticz_sensor_idx[idx]) { + if (Settings.domoticz_sensor_idx[idx]) { char dmess[64]; memcpy(dmess, mqtt_data, sizeof(dmess)); snprintf_P(mqtt_data, sizeof(dmess), PSTR("{\"idx\":%d,\"nvalue\":0,\"svalue\":\"%s\"}"), - sysCfg.domoticz_sensor_idx[idx], data); - mqtt_publish(domoticz_in_topic); + Settings.domoticz_sensor_idx[idx], data); + MqttPublish(domoticz_in_topic); memcpy(mqtt_data, dmess, sizeof(dmess)); } } -void domoticz_sensor1(char *temp) -{ - dom_sensor(0, temp); -} - -void domoticz_sensor2(char *temp, char *hum) +void DomoticzSensor(byte idx, uint32_t value) { char data[16]; - snprintf_P(data, sizeof(data), PSTR("%s;%s;%d"), temp, hum, dom_hum_stat(hum)); - dom_sensor(1, data); + snprintf_P(data, sizeof(data), PSTR("%d"), value); + DomoticzSensor(idx, data); } -void domoticz_sensor3(char *temp, char *hum, char *baro) +void DomoticzTempHumSensor(char *temp, char *hum) +{ + char data[16]; + snprintf_P(data, sizeof(data), PSTR("%s;%s;%d"), temp, hum, DomoticzHumidityState(hum)); + DomoticzSensor(DZ_TEMP_HUM, data); +} + +void DomoticzTempHumPressureSensor(char *temp, char *hum, char *baro) { char data[32]; - snprintf_P(data, sizeof(data), PSTR("%s;%s;%d;%s;5"), temp, hum, dom_hum_stat(hum), baro); - dom_sensor(2, data); + snprintf_P(data, sizeof(data), PSTR("%s;%s;%d;%s;5"), temp, hum, DomoticzHumidityState(hum), baro); + DomoticzSensor(DZ_TEMP_HUM_BARO, data); } -void domoticz_sensor4(uint16_t power, char *energy) +void DomoticzSensorPowerEnergy(uint16_t power, char *energy) { char data[16]; snprintf_P(data, sizeof(data), PSTR("%d;%s"), power, energy); - dom_sensor(3, data); -} - -void domoticz_sensor5(uint16_t lux) -{ - char data[8]; - snprintf_P(data, sizeof(data), PSTR("%d"), lux); - dom_sensor(4, data); -} - -void domoticz_sensor6(uint32_t count) -{ - char data[16]; - snprintf_P(data, sizeof(data), PSTR("%d"), count); - dom_sensor(5, data); + DomoticzSensor(DZ_POWER_ENERGY, data); } /*********************************************************************************************\ @@ -319,73 +308,73 @@ void domoticz_sensor6(uint32_t count) #ifdef USE_WEBSERVER const char S_CONFIGURE_DOMOTICZ[] PROGMEM = D_CONFIGURE_DOMOTICZ; -void handleDomoticz() +void HandleDomoticzConfiguration() { - if (HTTP_USER == _httpflag) { - handleRoot(); + if (HTTP_USER == webserver_state) { + HandleRoot(); return; } - addLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_DOMOTICZ); + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_DOMOTICZ); - char stemp[20]; + char stemp[32]; + char *sensortype; String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_CONFIGURE_DOMOTICZ)); page += FPSTR(HTTP_FORM_DOMOTICZ); - for (int i = 0; i < 4; i++) { - if (i < Maxdevice) { + for (int i = 0; i < MAX_DOMOTICZ_IDX; i++) { + if (i < devices_present) { page += FPSTR(HTTP_FORM_DOMOTICZ_RELAY); - page.replace("{2", String((int)sysCfg.domoticz_relay_idx[i])); - page.replace("{3", String((int)sysCfg.domoticz_key_idx[i])); + page.replace("{2", String((int)Settings.domoticz_relay_idx[i])); + page.replace("{3", String((int)Settings.domoticz_key_idx[i])); } if (pin[GPIO_SWT1 +i] < 99) { page += FPSTR(HTTP_FORM_DOMOTICZ_SWITCH); - page.replace("{4", String((int)sysCfg.domoticz_switch_idx[i])); + page.replace("{4", String((int)Settings.domoticz_switch_idx[i])); } page.replace("{1", String(i +1)); } - for (int i = 0; i < DOMOTICZ_MAX_SENSORS; i++) { + for (int i = 0; i < DZ_MAX_SENSORS; i++) { page += FPSTR(HTTP_FORM_DOMOTICZ_SENSOR); page.replace("{1", String(i +1)); - snprintf_P(stemp, sizeof(stemp), domoticz_sensors[i]); - page.replace("{2", stemp); - page.replace("{5", String((int)sysCfg.domoticz_sensor_idx[i])); + page.replace("{2", GetTextIndexed(stemp, sizeof(stemp), i, kDomoticzSensors)); + page.replace("{5", String((int)Settings.domoticz_sensor_idx[i])); } page += FPSTR(HTTP_FORM_DOMOTICZ_TIMER); - page.replace("{6", String((int)sysCfg.domoticz_update_timer)); + page.replace("{6", String((int)Settings.domoticz_update_timer)); page += F("
" D_DOMOTICZ_IDX " {1
" D_DOMOTICZ_KEY_IDX " {1
" D_DOMOTICZ_SWITCH_IDX " {1
" D_DOMOTICZ_IDX " {1
" D_DOMOTICZ_KEY_IDX " {1
" D_DOMOTICZ_SWITCH_IDX " {1
" D_DOMOTICZ_SENSOR_IDX " {1 - {2
" D_DOMOTICZ_SENSOR_IDX " {1 {2
" D_DOMOTICZ_UPDATE_TIMER " (" STR(DOMOTICZ_UPDATE_TIMER) ")
" D_DOMOTICZ_UPDATE_TIMER " (" STR(DOMOTICZ_UPDATE_TIMER) ")
"); page += FPSTR(HTTP_FORM_END); page += FPSTR(HTTP_BTN_CONF); - showPage(page); + ShowPage(page); } -void domoticz_saveSettings() +void DomoticzSaveSettings() { char stemp[20]; - for (byte i = 0; i < 4; i++) { + for (byte i = 0; i < MAX_DOMOTICZ_IDX; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("r%d"), i +1); - sysCfg.domoticz_relay_idx[i] = (!strlen(webServer->arg(stemp).c_str())) ? 0 : atoi(webServer->arg(stemp).c_str()); + Settings.domoticz_relay_idx[i] = (!strlen(WebServer->arg(stemp).c_str())) ? 0 : atoi(WebServer->arg(stemp).c_str()); snprintf_P(stemp, sizeof(stemp), PSTR("k%d"), i +1); - sysCfg.domoticz_key_idx[i] = (!strlen(webServer->arg(stemp).c_str())) ? 0 : atoi(webServer->arg(stemp).c_str()); + Settings.domoticz_key_idx[i] = (!strlen(WebServer->arg(stemp).c_str())) ? 0 : atoi(WebServer->arg(stemp).c_str()); snprintf_P(stemp, sizeof(stemp), PSTR("s%d"), i +1); - sysCfg.domoticz_switch_idx[i] = (!strlen(webServer->arg(stemp).c_str())) ? 0 : atoi(webServer->arg(stemp).c_str()); + Settings.domoticz_switch_idx[i] = (!strlen(WebServer->arg(stemp).c_str())) ? 0 : atoi(WebServer->arg(stemp).c_str()); } - for (byte i = 0; i < DOMOTICZ_MAX_SENSORS; i++) { + for (byte i = 0; i < DZ_MAX_SENSORS; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("l%d"), i +1); - sysCfg.domoticz_sensor_idx[i] = (!strlen(webServer->arg(stemp).c_str())) ? 0 : atoi(webServer->arg(stemp).c_str()); + Settings.domoticz_sensor_idx[i] = (!strlen(WebServer->arg(stemp).c_str())) ? 0 : atoi(WebServer->arg(stemp).c_str()); } - sysCfg.domoticz_update_timer = (!strlen(webServer->arg("ut").c_str())) ? DOMOTICZ_UPDATE_TIMER : atoi(webServer->arg("ut").c_str()); + Settings.domoticz_update_timer = (!strlen(WebServer->arg("ut").c_str())) ? DOMOTICZ_UPDATE_TIMER : atoi(WebServer->arg("ut").c_str()); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DOMOTICZ D_CMND_IDX " %d, %d, %d, %d, " D_CMND_UPDATETIMER " %d"), - sysCfg.domoticz_relay_idx[0], sysCfg.domoticz_relay_idx[1], sysCfg.domoticz_relay_idx[2], sysCfg.domoticz_relay_idx[3], - sysCfg.domoticz_update_timer); - addLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DOMOTICZ D_CMND_KEYIDX " %d, %d, %d, %d, " D_CMND_SWITCHIDX " %d, %d, %d, %d, " D_CMND_SENSORIDX " %d, %d, %d, %d, %d, %d"), - sysCfg.domoticz_key_idx[0], sysCfg.domoticz_key_idx[1], sysCfg.domoticz_key_idx[2], sysCfg.domoticz_key_idx[3], - sysCfg.domoticz_switch_idx[0], sysCfg.domoticz_switch_idx[1], sysCfg.domoticz_switch_idx[2], sysCfg.domoticz_switch_idx[3], - sysCfg.domoticz_sensor_idx[0], sysCfg.domoticz_sensor_idx[1], sysCfg.domoticz_sensor_idx[2], sysCfg.domoticz_sensor_idx[3], - sysCfg.domoticz_sensor_idx[4], sysCfg.domoticz_sensor_idx[5]); - addLog(LOG_LEVEL_INFO); + Settings.domoticz_relay_idx[0], Settings.domoticz_relay_idx[1], Settings.domoticz_relay_idx[2], Settings.domoticz_relay_idx[3], + Settings.domoticz_update_timer); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DOMOTICZ D_CMND_KEYIDX " %d, %d, %d, %d, " D_CMND_SWITCHIDX " %d, %d, %d, %d, " D_CMND_SENSORIDX " %d, %d, %d, %d, %d, %d, %d, %d"), + Settings.domoticz_key_idx[0], Settings.domoticz_key_idx[1], Settings.domoticz_key_idx[2], Settings.domoticz_key_idx[3], + Settings.domoticz_switch_idx[0], Settings.domoticz_switch_idx[1], Settings.domoticz_switch_idx[2], Settings.domoticz_switch_idx[3], + Settings.domoticz_sensor_idx[0], Settings.domoticz_sensor_idx[1], Settings.domoticz_sensor_idx[2], Settings.domoticz_sensor_idx[3], + Settings.domoticz_sensor_idx[4], Settings.domoticz_sensor_idx[5], Settings.domoticz_sensor_idx[6], Settings.domoticz_sensor_idx[7]); + AddLog(LOG_LEVEL_INFO); } #endif // USE_WEBSERVER #endif // USE_DOMOTICZ diff --git a/sonoff/xdrv_ir_send.ino b/sonoff/xdrv_ir_send.ino index ff89de9d9..fc88ed980 100644 --- a/sonoff/xdrv_ir_send.ino +++ b/sonoff/xdrv_ir_send.ino @@ -1,7 +1,7 @@ /* xdrv_ir_send.ino - infra red support for Sonoff-Tasmota - Copyright (C) 2017 Heiko Krupp and Theo Arends + Copyright (C) 2017 Heiko Krupp, Lazar Obradovic and 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 @@ -19,35 +19,39 @@ #ifdef USE_IR_REMOTE /*********************************************************************************************\ - * IR Remote send using IRremoteESP8266 library + * IR Remote send and receive using IRremoteESP8266 library \*********************************************************************************************/ #ifndef USE_IR_HVAC - #include +#include #else - #include +#include - // HVAC TOSHIBA_ - #define HVAC_TOSHIBA_HDR_MARK 4400 - #define HVAC_TOSHIBA_HDR_SPACE 4300 - #define HVAC_TOSHIBA_BIT_MARK 543 - #define HVAC_TOSHIBA_ONE_SPACE 1623 - #define HVAC_MISTUBISHI_ZERO_SPACE 472 - #define HVAC_TOSHIBA_RPT_MARK 440 - #define HVAC_TOSHIBA_RPT_SPACE 7048 // Above original iremote limit - #define HVAC_TOSHIBA_DATALEN 9 +// HVAC TOSHIBA_ +#define HVAC_TOSHIBA_HDR_MARK 4400 +#define HVAC_TOSHIBA_HDR_SPACE 4300 +#define HVAC_TOSHIBA_BIT_MARK 543 +#define HVAC_TOSHIBA_ONE_SPACE 1623 +#define HVAC_MISTUBISHI_ZERO_SPACE 472 +#define HVAC_TOSHIBA_RPT_MARK 440 +#define HVAC_TOSHIBA_RPT_SPACE 7048 // Above original iremote limit +#define HVAC_TOSHIBA_DATALEN 9 - IRMitsubishiAC *mitsubir = NULL; +IRMitsubishiAC *mitsubir = NULL; - const char FANSPEED[] = "A12345S"; - const char HVACMODE[] = "HDCA"; +const char kFanSpeedOptions[] = "A12345S"; +const char kHvacModeOptions[] = "HDCA"; #endif +/*********************************************************************************************\ + * IR Send +\*********************************************************************************************/ + IRsend *irsend = NULL; -void ir_send_init(void) +void IrSendInit(void) { - irsend = new IRsend(pin[GPIO_IRSEND]); // an IR led is at GPIO_IRSEND + irsend = new IRsend(pin[GPIO_IRSEND]); // an IR led is at GPIO_IRSEND irsend->begin(); #ifdef USE_IR_HVAC @@ -55,138 +59,106 @@ void ir_send_init(void) #endif //USE_IR_HVAC } +#ifdef USE_IR_RECEIVE /*********************************************************************************************\ - * Commands + * IR Receive \*********************************************************************************************/ -/* - * ArduinoJSON entry used to calculate jsonBuf: JSON_OBJECT_SIZE(3) + 40 = 96 - IRsend: - { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } +#define IR_TIME_AVOID_DUPLICATE 500 // Milliseconds - IRhvac: - { "Vendor": "", "Power": <0|1>, "Mode": "", "FanSpeed": "<1|2|3|4|5|Auto|Silence>", "Temp": <17..30> } -*/ +// Based on IRremoteESP8266.h enum decode_type_t +const char kIrRemoteProtocols[] PROGMEM = + "UNKNOWN|RC5|RC6|NEC|SONY|PANASONIC|JVC|SAMSUNG|WHYNTER|AIWA_RC_T501|LG|SANYO|MITSUBISHI|DISH|SHARP"; -boolean ir_send_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload) +IRrecv *irrecv = NULL; +unsigned long ir_lasttime = 0; + +void IrReceiveInit(void) { - boolean serviced = true; - boolean error = false; - const char *protocol; - uint8_t bits = 0; - uint32_t data = 0; + irrecv = new IRrecv(pin[GPIO_IRRECV]); // an IR led is at GPIO_IRRECV + irrecv->enableIRIn(); // Start the receiver - const char *HVAC_Mode; - const char *HVAC_FanMode; - const char *HVAC_Vendor; - int HVAC_Temp = 21; - boolean HVAC_Power = true; - - if (!strcasecmp_P(type, PSTR(D_CMND_IRSEND))) { - if (data_len) { - StaticJsonBuffer<128> jsonBuf; - JsonObject &ir_json = jsonBuf.parseObject(dataBuf); - if (!ir_json.success()) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_INVALID_JSON "\"}")); // JSON decode failed - } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_DONE "\"}")); - protocol = ir_json[D_IRSEND_PROTOCOL]; - bits = ir_json[D_IRSEND_BITS]; - data = ir_json[D_IRSEND_DATA]; - if (protocol && bits && data) { - if (!strcasecmp_P(protocol, PSTR("NEC"))) irsend->sendNEC(data, bits); - else if (!strcasecmp_P(protocol, PSTR("SONY"))) irsend->sendSony(data, bits); - else if (!strcasecmp_P(protocol, PSTR("RC5"))) irsend->sendRC5(data, bits); - else if (!strcasecmp_P(protocol, PSTR("RC6"))) irsend->sendRC6(data, bits); - else if (!strcasecmp_P(protocol, PSTR("DISH"))) irsend->sendDISH(data, bits); - else if (!strcasecmp_P(protocol, PSTR("JVC"))) irsend->sendJVC(data, bits, 1); - else if (!strcasecmp_P(protocol, PSTR("SAMSUNG"))) irsend->sendSAMSUNG(data, bits); - else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_PROTOCOL_NOT_SUPPORTED "\"}")); - } - } else error = true; - } - } else error = true; - if (error) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_NO D_IRSEND_PROTOCOL ", " D_IRSEND_BITS " " D_OR " " D_IRSEND_DATA "\"}")); - } - } -#ifdef USE_IR_HVAC - else if (!strcasecmp_P(type, PSTR(D_CMND_IRHVAC))) { - if (data_len) { - StaticJsonBuffer<164> jsonBufer; - JsonObject &root = jsonBufer.parseObject(dataBuf); - if (!root.success()) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRHVAC "\":\"" D_INVALID_JSON "\"}")); // JSON decode failed - } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRHVAC "\":\"" D_DONE "\"}")); - HVAC_Vendor = root[D_IRHVAC_VENDOR]; - HVAC_Power = root[D_IRHVAC_POWER]; - HVAC_Mode = root[D_IRHVAC_MODE]; - HVAC_FanMode = root[D_IRHVAC_FANSPEED]; - HVAC_Temp = root[D_IRHVAC_TEMP]; - -// snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: Received Vendor %s, Power %d, Mode %s, FanSpeed %s, Temp %d"), -// HVAC_Vendor, HVAC_Power, HVAC_Mode, HVAC_FanMode, HVAC_Temp); -// addLog(LOG_LEVEL_DEBUG); - - if (HVAC_Vendor == NULL || !strcasecmp_P(HVAC_Vendor, PSTR("TOSHIBA"))) { - error = ir_hvac_toshiba(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); - } - else if (!strcasecmp_P(HVAC_Vendor, PSTR("MITSUBISHI"))) { - error = ir_hvac_mitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); - } - else error = true; - } - } else error = true; - if (error) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRHVAC "\":\"" D_WRONG D_IRHVAC_VENDOR ", " D_IRHVAC_MODE " " D_OR " " D_IRHVAC_FANSPEED "\"}")); - } - } -#endif // USE_IR_HVAC - else { - serviced = false; // Unknown command - } - return serviced; + // AddLog_P(LOG_LEVEL_DEBUG, PSTR("IrReceive initialized")); } -#ifdef USE_IR_HVAC -boolean ir_hvac_toshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) +void IrReceiveCheck() { - unsigned int rawdata[2 + 2*8*HVAC_TOSHIBA_DATALEN + 2]; - byte data[HVAC_TOSHIBA_DATALEN] = { 0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00 }; + char sirtype[14]; // Max is AIWA_RC_T501 + int8_t iridx = 0; + + decode_results results; + + if (irrecv->decode(&results)) { + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_IRR "RawLen %d, Bits %d, Value %08X, Decode %d"), + results.rawlen, results.bits, results.value, results.decode_type); + AddLog(LOG_LEVEL_DEBUG); + + unsigned long now = millis(); + if ((now - ir_lasttime > IR_TIME_AVOID_DUPLICATE) && (UNKNOWN != results.decode_type) && (results.bits > 0)) { + ir_lasttime = now; + + iridx = results.decode_type; + if ((iridx < 0) || (iridx > 14)) { + iridx = 0; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_IRRECEIVED "\":{\"" D_IR_PROTOCOL "\":\"%s\", \"" D_IR_BITS "\":%d, \"" D_IR_DATA "\":\"%X\"}}"), + GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits, results.value); + MqttPublishPrefixTopic_P(6, PSTR(D_IRRECEIVED)); +#ifdef USE_DOMOTICZ + unsigned long value = results.value | (iridx << 28); // [Protocol:4, Data:28] + DomoticzSensor(DZ_COUNT, value); // Send data as Domoticz Counter value +#endif // USE_DOMOTICZ + } + + irrecv->resume(); + } +} +#endif // USE_IR_RECEIVE + +#ifdef USE_IR_HVAC +/*********************************************************************************************\ + * IR Heating, Ventilation and Air Conditioning using IRMitsubishiAC library +\*********************************************************************************************/ + +boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) +{ + unsigned int rawdata[2 + 2 * 8 * HVAC_TOSHIBA_DATALEN + 2]; + byte data[HVAC_TOSHIBA_DATALEN] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00}; char *p; char *token; uint8_t mode; if (HVAC_Mode == NULL) { - p = (char*)HVACMODE; // default HVAC_HOT - } else { - p = strchr(HVACMODE, toupper(HVAC_Mode[0])); + p = (char *)kHvacModeOptions; // default HVAC_HOT + } + else { + p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); } if (!p) { return true; } - data[6] = (p - HVACMODE) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00 + data[6] = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00 if (!HVAC_Power) { - data[6] = (byte) 0x07; // Turn OFF HVAC + data[6] = (byte)0x07; // Turn OFF HVAC } if (HVAC_FanMode == NULL) { - p = (char*)FANSPEED; // default FAN_SPEED_AUTO - } else { - p = strchr(FANSPEED, toupper(HVAC_FanMode[0])); + p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO + } + else { + p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); } if (!p) { return true; } - mode = p - FANSPEED +1; + mode = p - kFanSpeedOptions + 1; if ((1 == mode) || (7 == mode)) { mode = 0; } - mode = mode << 5; // AUTO = 0x00, SPEED = 0x40, 0x60, 0x80, 0xA0, 0xC0, SILENT = 0x00 + mode = mode << 5; // AUTO = 0x00, SPEED = 0x40, 0x60, 0x80, 0xA0, 0xC0, SILENT = 0x00 data[6] = data[6] | mode; byte Temp; @@ -199,11 +171,11 @@ boolean ir_hvac_toshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean else { Temp = HVAC_Temp; } - data[5] = (byte) Temp - 17 << 4; + data[5] = (byte)Temp - 17 << 4; - data[HVAC_TOSHIBA_DATALEN-1] = 0; + data[HVAC_TOSHIBA_DATALEN - 1] = 0; for (int x = 0; x < HVAC_TOSHIBA_DATALEN - 1; x++) { - data[HVAC_TOSHIBA_DATALEN-1] = (byte) data[x] ^ data[HVAC_TOSHIBA_DATALEN -1]; // CRC is a simple bits addition + data[HVAC_TOSHIBA_DATALEN - 1] = (byte)data[x] ^ data[HVAC_TOSHIBA_DATALEN - 1]; // CRC is a simple bits addition } int i = 0; @@ -232,14 +204,14 @@ boolean ir_hvac_toshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean rawdata[i++] = HVAC_TOSHIBA_RPT_SPACE; noInterrupts(); - irsend->sendRaw(rawdata,i,38); - irsend->sendRaw(rawdata,i,38); + irsend->sendRaw(rawdata, i, 38); + irsend->sendRaw(rawdata, i, 38); interrupts(); return false; } -boolean ir_hvac_mitsubishi(const char *HVAC_Mode,const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) +boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) { char *p; char *token; @@ -248,38 +220,164 @@ boolean ir_hvac_mitsubishi(const char *HVAC_Mode,const char *HVAC_FanMode, boole mitsubir->stateReset(); if (HVAC_Mode == NULL) { - p = (char*)HVACMODE; // default HVAC_HOT - } else { - p = strchr(HVACMODE, toupper(HVAC_Mode[0])); + p = (char *)kHvacModeOptions; // default HVAC_HOT + } + else { + p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); } if (!p) { return true; } - mode = (p - HVACMODE +1) << 3; // HOT = 0x08, DRY = 0x10, COOL = 0x18, AUTO = 0x20 + mode = (p - kHvacModeOptions + 1) << 3; // HOT = 0x08, DRY = 0x10, COOL = 0x18, AUTO = 0x20 mitsubir->setMode(mode); mitsubir->setPower(HVAC_Power); if (HVAC_FanMode == NULL) { - p = (char*)FANSPEED; // default FAN_SPEED_AUTO - } else { - p = strchr(FANSPEED, toupper(HVAC_FanMode[0])); + p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO + } + else { + p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); } if (!p) { return true; } - mode = p - FANSPEED; // AUTO = 0, SPEED = 1 .. 5, SILENT = 6 + mode = p - kFanSpeedOptions; // AUTO = 0, SPEED = 1 .. 5, SILENT = 6 mitsubir->setFan(mode); mitsubir->setTemp(HVAC_Temp); mitsubir->setVane(MITSUBISHI_AC_VANE_AUTO); mitsubir->send(); -// snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: Mitsubishi Power %d, Mode %d, FanSpeed %d, Temp %d, VaneMode %d"), -// mitsubir->getPower(), mitsubir->getMode(), mitsubir->getFan(), mitsubir->getTemp(), mitsubir->getVane()); -// addLog(LOG_LEVEL_DEBUG); + // snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: Mitsubishi Power %d, Mode %d, FanSpeed %d, Temp %d, VaneMode %d"), + // mitsubir->getPower(), mitsubir->getMode(), mitsubir->getFan(), mitsubir->getTemp(), mitsubir->getVane()); + // AddLog(LOG_LEVEL_DEBUG); return false; } -#endif // USE_IR_HVAC -#endif // USE_IR_REMOTE +#endif // USE_IR_HVAC + +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ + +/* + * ArduinoJSON entry used to calculate jsonBuf: JSON_OBJECT_SIZE(3) + 40 = 96 + IRsend: + { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } + + IRhvac: + { "Vendor": "", "Power": <0|1>, "Mode": "", "FanSpeed": "<1|2|3|4|5|Auto|Silence>", "Temp": <17..30> } +*/ + +boolean IrSendCommand(char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload) +{ + boolean serviced = true; + boolean error = false; + char dataBufUc[data_len]; + char protocol_text[20]; + const char *protocol; + uint32_t bits = 0; + uint32_t data = 0; + + const char *HVAC_Mode; + const char *HVAC_FanMode; + const char *HVAC_Vendor; + int HVAC_Temp = 21; + boolean HVAC_Power = true; + + for (uint16_t i = 0; i <= sizeof(dataBufUc); i++) { + dataBufUc[i] = toupper(dataBuf[i]); + } + if (!strcasecmp_P(type, PSTR(D_CMND_IRSEND))) { + if (data_len) { + StaticJsonBuffer<128> jsonBuf; + JsonObject &ir_json = jsonBuf.parseObject(dataBufUc); + if (!ir_json.success()) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_INVALID_JSON "\"}")); // JSON decode failed + } + else { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_DONE "\"}")); + protocol = ir_json[D_IR_PROTOCOL]; + bits = ir_json[D_IR_BITS]; + data = ir_json[D_IR_DATA]; + if (protocol && bits && data) { + int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); + switch (protocol_code) { + case NEC: + irsend->sendNEC(data, bits); break; + case SONY: + irsend->sendSony(data, bits); break; + case RC5: + irsend->sendRC5(data, bits); break; + case RC6: + irsend->sendRC6(data, bits); break; + case DISH: + irsend->sendDISH(data, bits); break; + case JVC: + irsend->sendJVC(data, bits, 1); break; + case SAMSUNG: + irsend->sendSAMSUNG(data, bits); break; + case PANASONIC: + irsend->sendPanasonic(bits, data); break; + default: + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_PROTOCOL_NOT_SUPPORTED "\"}")); + } + } + else { + error = true; + } + } + } + else { + error = true; + } + if (error) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_NO " " D_IR_PROTOCOL ", " D_IR_BITS " " D_OR " " D_IR_DATA "\"}")); + } + } +#ifdef USE_IR_HVAC + else if (!strcasecmp_P(type, PSTR(D_CMND_IRHVAC))) { + if (data_len) { + StaticJsonBuffer<164> jsonBufer; + JsonObject &root = jsonBufer.parseObject(dataBufUc); + if (!root.success()) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRHVAC "\":\"" D_INVALID_JSON "\"}")); // JSON decode failed + } + else { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRHVAC "\":\"" D_DONE "\"}")); + HVAC_Vendor = root[D_IRHVAC_VENDOR]; + HVAC_Power = root[D_IRHVAC_POWER]; + HVAC_Mode = root[D_IRHVAC_MODE]; + HVAC_FanMode = root[D_IRHVAC_FANSPEED]; + HVAC_Temp = root[D_IRHVAC_TEMP]; + + // snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: Received Vendor %s, Power %d, Mode %s, FanSpeed %s, Temp %d"), + // HVAC_Vendor, HVAC_Power, HVAC_Mode, HVAC_FanMode, HVAC_Temp); + // AddLog(LOG_LEVEL_DEBUG); + + if (HVAC_Vendor == NULL || !strcasecmp_P(HVAC_Vendor, PSTR("TOSHIBA"))) { + error = IrHvacToshiba(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); + } + else if (!strcasecmp_P(HVAC_Vendor, PSTR("MITSUBISHI"))) { + error = IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); + } + else { + error = true; + } + } + } + else { + error = true; + } + if (error) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRHVAC "\":\"" D_WRONG " " D_IRHVAC_VENDOR ", " D_IRHVAC_MODE " " D_OR " " D_IRHVAC_FANSPEED "\"}")); + } + } +#endif // USE_IR_HVAC + else { + serviced = false; // Unknown command + } + return serviced; +} +#endif // USE_IR_REMOTE diff --git a/sonoff/xdrv_snfbridge.ino b/sonoff/xdrv_snfbridge.ino index 4d366eb76..96e78e3f5 100644 --- a/sonoff/xdrv_snfbridge.ino +++ b/sonoff/xdrv_snfbridge.ino @@ -23,128 +23,153 @@ #define SFB_TIME_AVOID_DUPLICATE 2000 // Milliseconds -uint8_t sfb_rcvflg = 0; -uint8_t sfb_learnKey = 1; -uint8_t sfb_learnFlg = 0; -uint32_t sfb_lastrid = 0; -unsigned long sfb_lasttime = 0; +enum SonoffBridgeCommands { + CMND_RFSYNC, CMND_RFLOW, CMND_RFHIGH, CMND_RFHOST, CMND_RFCODE, CMND_RFKEY }; +const char kSonoffBridgeCommands[] PROGMEM = + D_CMND_RFSYNC "|" D_CMND_RFLOW "|" D_CMND_RFHIGH "|" D_CMND_RFHOST "|" D_CMND_RFCODE "|" D_CMND_RFKEY ; -void sb_received() +uint8_t sonoff_bridge_receive_flag = 0; +uint8_t sonoff_bridge_learn_key = 1; +uint8_t sonoff_bridge_learn_active = 0; +uint32_t sonoff_bridge_last_received_id = 0; +uint32_t sonoff_bridge_last_send_code = 0; +unsigned long sonoff_bridge_last_time = 0; + +void SonoffBridgeReceived() { - uint8_t i = 0; - uint32_t sid = 0; - uint32_t rid = 0; - uint16_t rsy = 0; - uint16_t rlo = 0; - uint16_t rhi = 0; + uint16_t sync_time = 0; + uint16_t low_time = 0; + uint16_t high_time = 0; + uint32_t received_id = 0; char svalue[90]; char rfkey[8]; svalue[0] = '\0'; - for (i = 0; i < SerialInByteCounter; i++) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s%02X "), svalue, serialInBuf[i]); + for (byte i = 0; i < serial_in_byte_counter; i++) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s%02X "), svalue, serial_in_buffer[i]); } snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_BRIDGE D_RECEIVED " %s"), svalue); - addLog(LOG_LEVEL_DEBUG); + AddLog(LOG_LEVEL_DEBUG); - if (0xA2 == serialInBuf[0]) { // Learn timeout - sfb_learnFlg = 0; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFKEY "%d\":\"" D_LEARN_FAILED "\"}"), sfb_learnKey); - mqtt_publish_topic_P(5, PSTR(D_CMND_RFKEY)); + if (0xA2 == serial_in_buffer[0]) { // Learn timeout + sonoff_bridge_learn_active = 0; + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, sonoff_bridge_learn_key, D_LEARN_FAILED); + MqttPublishPrefixTopic_P(5, PSTR(D_CMND_RFKEY)); } - else if (0xA3 == serialInBuf[0]) { // Learned A3 20 F8 01 18 03 3E 2E 1A 22 55 - sfb_learnFlg = 0; - rlo = serialInBuf[3] << 8 | serialInBuf[4]; // Low time in uSec - rhi = serialInBuf[5] << 8 | serialInBuf[6]; // High time in uSec - if (rlo && rhi) { - for (i = 0; i < 9; i++) { - sysCfg.sfb_code[sfb_learnKey][i] = serialInBuf[i +1]; + else if (0xA3 == serial_in_buffer[0]) { // Learned A3 20 F8 01 18 03 3E 2E 1A 22 55 + sonoff_bridge_learn_active = 0; + low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; // Low time in uSec + high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; // High time in uSec + if (low_time && high_time) { + for (byte i = 0; i < 9; i++) { + Settings.rf_code[sonoff_bridge_learn_key][i] = serial_in_buffer[i +1]; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFKEY "%d\":\"" D_LEARNED "\"}"), sfb_learnKey); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, sonoff_bridge_learn_key, D_LEARNED); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFKEY "%d\":\"" D_LEARN_FAILED "\"}"), sfb_learnKey); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, sonoff_bridge_learn_key, D_LEARN_FAILED); } - mqtt_publish_topic_P(5, PSTR(D_CMND_RFKEY)); + MqttPublishPrefixTopic_P(5, PSTR(D_CMND_RFKEY)); } - else if (0xA4 == serialInBuf[0]) { // Received RF data A4 20 EE 01 18 03 3E 2E 1A 22 55 - rsy = serialInBuf[1] << 8 | serialInBuf[2]; // Sync time in uSec - rlo = serialInBuf[3] << 8 | serialInBuf[4]; // Low time in uSec - rhi = serialInBuf[5] << 8 | serialInBuf[6]; // High time in uSec - rid = serialInBuf[7] << 16 | serialInBuf[8] << 8 | serialInBuf[9]; + else if (0xA4 == serial_in_buffer[0]) { // Received RF data A4 20 EE 01 18 03 3E 2E 1A 22 55 + sync_time = serial_in_buffer[1] << 8 | serial_in_buffer[2]; // Sync time in uSec + low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; // Low time in uSec + high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; // High time in uSec + received_id = serial_in_buffer[7] << 16 | serial_in_buffer[8] << 8 | serial_in_buffer[9]; unsigned long now = millis(); - if (!((rid == sfb_lastrid) && (now - sfb_lasttime < SFB_TIME_AVOID_DUPLICATE))) { - sfb_lastrid = rid; - sfb_lasttime = now; + if (!((received_id == sonoff_bridge_last_received_id) && (now - sonoff_bridge_last_time < SFB_TIME_AVOID_DUPLICATE))) { + sonoff_bridge_last_received_id = received_id; + sonoff_bridge_last_time = now; strncpy_P(rfkey, PSTR("\"" D_NONE "\""), sizeof(rfkey)); - for (i = 1; i <= 16; i++) { - if (sysCfg.sfb_code[i][0]) { - sid = sysCfg.sfb_code[i][6] << 16 | sysCfg.sfb_code[i][7] << 8 | sysCfg.sfb_code[i][8]; - if (sid == rid) { + for (byte i = 1; i <= 16; i++) { + if (Settings.rf_code[i][0]) { + uint32_t send_id = Settings.rf_code[i][6] << 16 | Settings.rf_code[i][7] << 8 | Settings.rf_code[i][8]; + if (send_id == received_id) { snprintf_P(rfkey, sizeof(rfkey), PSTR("%d"), i); break; } } } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_RFRECEIVED "\":{\"" D_SYNC "\":%d, \"" D_LOW "\":%d, \"" D_HIGH "\":%d, \"" D_DATA "\":\"%06X\", \"" D_CMND_RFKEY "\":%s}}"), - rsy, rlo, rhi, rid, rfkey); - mqtt_publish_topic_P(6, PSTR(D_RFRECEIVED)); + sync_time, low_time, high_time, received_id, rfkey); + MqttPublishPrefixTopic_P(6, PSTR(D_RFRECEIVED)); +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_COUNT, received_id); // Send rid as Domoticz Counter value +#endif // USE_DOMOTICZ } } } -boolean sb_serial() +boolean SonoffBridgeSerialInput() { - if (sfb_rcvflg) { - if (!((SerialInByteCounter == 0) && (SerialInByte == 0))) { // Skip leading 0 - serialInBuf[SerialInByteCounter++] = SerialInByte; - if (0x55 == SerialInByte) { // 0x55 - End of text - sb_received(); - sfb_rcvflg = 0; + if (sonoff_bridge_receive_flag) { + if (!((serial_in_byte_counter == 0) && (serial_in_byte == 0))) { // Skip leading 0 + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (0x55 == serial_in_byte) { // 0x55 - End of text + SonoffBridgeReceived(); + sonoff_bridge_receive_flag = 0; return 1; } } - SerialInByte = 0; + serial_in_byte = 0; } - if (0xAA == SerialInByte) { // 0xAA - Start of text - SerialInByteCounter = 0; - SerialInByte = 0; - sfb_rcvflg = 1; + if (0xAA == serial_in_byte) { // 0xAA - Start of text + serial_in_byte_counter = 0; + serial_in_byte = 0; + sonoff_bridge_receive_flag = 1; } return 0; } -void sb_sendAck() +void SonoffBridgeSendAck() { Serial.write(0xAA); // Start of Text Serial.write(0xA0); // Acknowledge Serial.write(0x55); // End of Text } -void sb_send(uint8_t idx, uint8_t key) +void SonoffBridgeSendCode(uint32_t code) +{ + Serial.write(0xAA); // Start of Text + Serial.write(0xA5); // Send following code + for (byte i = 0; i < 6; i++) { + Serial.write(Settings.rf_code[0][i]); + } + Serial.write((code >> 16) & 0xff); + Serial.write((code >> 8) & 0xff); + Serial.write(code & 0xff); + Serial.write(0x55); // End of Text + Serial.flush(); +} + +void SonoffBridgeSend(uint8_t idx, uint8_t key) { uint8_t code; key--; // Support 1 to 16 Serial.write(0xAA); // Start of Text Serial.write(0xA5); // Send following code - for (uint8_t i = 0; i < 8; i++) { - Serial.write(sysCfg.sfb_code[idx][i]); + for (byte i = 0; i < 8; i++) { + Serial.write(Settings.rf_code[idx][i]); } if (0 == idx) { - code = (0x10 << (key >> 2)) | (0x01 << (key & 3)); // 11,12,14,18,21,22,24,28,41,42,44,48,81,82,84,88 + code = (0x10 << (key >> 2)) | (1 << (key & 3)); // 11,12,14,18,21,22,24,28,41,42,44,48,81,82,84,88 } else { - code = sysCfg.sfb_code[idx][8]; + code = Settings.rf_code[idx][8]; } Serial.write(code); Serial.write(0x55); // End of Text Serial.flush(); +#ifdef USE_DOMOTICZ +// uint32_t rid = Settings.rf_code[idx][6] << 16 | Settings.rf_code[idx][7] << 8 | code; +// DomoticzSensor(DZ_COUNT, rid); // Send rid as Domoticz Counter value +#endif // USE_DOMOTICZ } -void sb_learn(uint8_t key) +void SonoffBridgeLearn(uint8_t key) { - sfb_learnKey = key; - sfb_learnFlg = 1; + sonoff_bridge_learn_key = key; + sonoff_bridge_learn_active = 1; Serial.write(0xAA); // Start of Text Serial.write(0xA1); // Start learning Serial.write(0x55); // End of Text @@ -154,47 +179,90 @@ void sb_learn(uint8_t key) * Commands \*********************************************************************************************/ -boolean sb_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload) +boolean SonoffBridgeCommand(char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload) { + char command [CMDSZ]; boolean serviced = true; - char *p; - if (!strcasecmp_P(type, PSTR(D_CMND_RFDEFAULT))) { - if (4 == data_len) { - uint16_t hexcode = strtol(dataBuf, &p, 16); - uint8_t msb = hexcode >> 8; - uint8_t lsb = hexcode & 0xFF; - if ((hexcode > 0) && (hexcode < 0x7FFF) && (msb != 0x55) && (lsb != 0x55)) { - sysCfg.sfb_code[0][6] = msb; - sysCfg.sfb_code[0][7] = lsb; + int command_code = GetCommandCode(command, sizeof(command), type, kSonoffBridgeCommands); + if ((command_code >= CMND_RFSYNC) && (command_code <= CMND_RFCODE)) { // RfSync, RfLow, RfHigh, RfHost and RfCode + char *p; + char stemp [10]; + uint32_t code = 0; + uint8_t radix = 10; + + uint8_t set_index = command_code *2; + + if (dataBuf[0] == '#') { + dataBuf++; + data_len--; + radix = 16; + } + + if (data_len) { + code = strtol(dataBuf, &p, radix); + if (code) { + if (CMND_RFCODE == command_code) { + sonoff_bridge_last_send_code = code; + SonoffBridgeSendCode(code); + } else { + if (1 == payload) { + code = pgm_read_byte(kDefaultRfCode + set_index) << 8 | pgm_read_byte(kDefaultRfCode + set_index +1); + } + uint8_t msb = code >> 8; + uint8_t lsb = code & 0xFF; + if ((code > 0) && (code < 0x7FFF) && (msb != 0x55) && (lsb != 0x55)) { // Check for End of Text codes + Settings.rf_code[0][set_index] = msb; + Settings.rf_code[0][set_index +1] = lsb; + } + } } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFDEFAULT "\":\"%0X%0X\"}"), sysCfg.sfb_code[0][6], sysCfg.sfb_code[0][7]); + if (CMND_RFCODE == command_code) { + code = sonoff_bridge_last_send_code; + } else { + code = Settings.rf_code[0][set_index] << 8 | Settings.rf_code[0][set_index +1]; + } + if (10 == radix) { + snprintf_P(stemp, sizeof(stemp), PSTR("%d"), code); + } else { + snprintf_P(stemp, sizeof(stemp), PSTR("\"#%X\""), code); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_XVALUE, command, stemp); } - else if (!strcasecmp_P(type, PSTR(D_CMND_RFKEY)) && (index > 0) && (index <= 16)) { - if (!sfb_learnFlg) { - if (2 == payload) { - sb_learn(index); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFKEY "%d\":\"" D_START_LEARNING "\"}"), index); + else if ((CMND_RFKEY == command_code) && (index > 0) && (index <= 16)) { + if (!sonoff_bridge_learn_active) { + if (2 == payload) { // Learn RF data + SonoffBridgeLearn(index); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, D_START_LEARNING); } - else if (3 == payload) { - sysCfg.sfb_code[index][0] = 0; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFKEY "%d\":\"" D_SET_TO_DEFAULT "\"}"), index); + else if (3 == payload) { // Unlearn RF data + Settings.rf_code[index][0] = 0; + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, D_SET_TO_DEFAULT); + } + else if (4 == payload) { // Save RF data provided by RFSync, RfLow, RfHigh and last RfCode + for (byte i = 0; i < 6; i++) { + Settings.rf_code[index][i] = Settings.rf_code[0][i]; + } + Settings.rf_code[index][6] = (sonoff_bridge_last_send_code >> 16) & 0xff; + Settings.rf_code[index][7] = (sonoff_bridge_last_send_code >> 8) & 0xff; + Settings.rf_code[index][8] = sonoff_bridge_last_send_code & 0xff; + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, D_SAVED); } else { - if ((1 == payload) || (0 == sysCfg.sfb_code[index][0])) { - sb_send(0, index); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFKEY "%d\":\"" D_DEFAULT_SENT "\"}"), index); + if ((1 == payload) || (0 == Settings.rf_code[index][0])) { + SonoffBridgeSend(0, index); // Send default RF data + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, D_DEFAULT_SENT); } else { - sb_send(index, 0); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFKEY "%d\":\"" D_LEARNED_SENT "\"}"), index); + SonoffBridgeSend(index, 0); // Send learned RF data + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, D_LEARNED_SENT); } } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFKEY "%d\":\"" D_LEARNING_ACTIVE "\"}"), sfb_learnKey); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, sonoff_bridge_learn_key, D_LEARNING_ACTIVE); } + } else { + serviced = false; } - else { - serviced = false; // Unknown command - } + return serviced; } diff --git a/sonoff/xdrv_snfled.ino b/sonoff/xdrv_snfled.ino index 7424026ce..4bdc96b23 100644 --- a/sonoff/xdrv_snfled.ino +++ b/sonoff/xdrv_snfled.ino @@ -1,5 +1,5 @@ /* - xdrv_snfled.ino - WS2812 and sonoff led support for Sonoff-Tasmota + xdrv_snfled.ino - PWM, WS2812 and sonoff led support for Sonoff-Tasmota Copyright (C) 2017 Theo Arends @@ -18,29 +18,46 @@ */ /*********************************************************************************************\ - * WS2812, Sonoff B1, AiLight, Sonoff Led and BN-SZ01 + * PWM, WS2812, Sonoff B1, AiLight, Sonoff Led and BN-SZ01, H801, MagicHome and Arilux * - * sfl_flg Module Color ColorTemp - * 1 Sonoff BN-SZ W no - * 2 Sonoff Led CW yes - * 3 +WS2812 RGB no - * 4 AiLight RGBW no - * 5 Sonoff B1 RGBCW yes + * light_type Module Color ColorTemp Modules + * ---------- --------- ----- --------- ---------------------------- + * 1 PWM1 W no (Sonoff BN-SZ) + * 2 PWM2 CW yes (Sonoff Led) + * 3 PWM3 RGB no (H801, MagicHome and Arilux) + * 4 PWM4 RGBW no (H801, MagicHome and Arilux) + * 5 PWM5 RGBCW yes (H801, Arilux) + * 9 reserved no + * 10 reserved yes + * 11 +WS2812 RGB no + * 12 AiLight RGBW no + * 13 Sonoff B1 RGBCW yes * - * led_scheme WS2812 Others Effect - * 0 yes yes Color On/Off - * 1 yes yes Wakeup light - * 2 yes no Clock - * 3 yes no Incandescent - * 4 yes no RGB - * 5 yes no Christmas - * 6 yes no Hanukkah - * 7 yes no Kwanzaa - * 8 yes no Rainbow - * 9 yes no Fire + * light_scheme WS2812 3+ Colors 1+2 Colors Effect + * ------------ ------ --------- ---------- ----------------- + * 0 yes yes yes Color On/Off + * 1 yes yes yes Wakeup light + * 2 yes yes no Color cycle RGB + * 3 yes yes no Color cycle RBG + * 4 yes yes no Random RGB colors + * 5 yes no no Clock + * 6 yes no no Incandescent + * 7 yes no no RGB + * 8 yes no no Christmas + * 9 yes no no Hanukkah + * 10 yes no no Kwanzaa + * 11 yes no no Rainbow + * 12 yes no no Fire * \*********************************************************************************************/ +enum LightCommands { + CMND_COLOR, CMND_COLORTEMPERATURE, CMND_DIMMER, CMND_LED, CMND_LEDTABLE, CMND_FADE, + CMND_PIXELS, CMND_SCHEME, CMND_SPEED, CMND_WAKEUP, CMND_WAKEUPDURATION, CMND_WIDTH, CMND_UNDOCA }; +const char kLightCommands[] PROGMEM = + D_CMND_COLOR "|" D_CMND_COLORTEMPERATURE "|" D_CMND_DIMMER "|" D_CMND_LED "|" D_CMND_LEDTABLE "|" D_CMND_FADE "|" + D_CMND_PIXELS "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" D_CMND_WIDTH "|UNDOCA" ; + uint8_t ledTable[] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -59,17 +76,20 @@ uint8_t ledTable[] = { 184,186,189,191,193,195,197,199,201,204,206,208,210,212,215,217, 219,221,224,226,228,231,233,235,238,240,243,245,248,250,253,255 }; -uint8_t sl_dcolor[5]; -uint8_t sl_tcolor[5]; -uint8_t sl_lcolor[5]; +uint8_t light_entry_color[5]; +uint8_t light_current_color[5]; +uint8_t light_new_color[5]; +uint8_t light_last_color[5]; -uint8_t sl_power = 0; -uint8_t sl_any = 0; -uint8_t sl_wakeupActive = 0; -uint8_t sl_wakeupDimmer = 0; -uint16_t sl_wakeupCntr = 0; +uint8_t light_wheel = 0; +uint8_t light_subtype = 0; +uint8_t light_power = 0; +uint8_t light_update = 1; +uint8_t light_wakeup_active = 0; +uint8_t light_wakeup_dimmer = 0; +uint16_t light_wakeup_counter = 0; -unsigned long stripTimerCntr = 0; // Bars and Gradient +unsigned long strip_timer_counter = 0; // Bars and Gradient /*********************************************************************************************\ * Sonoff B1 and AiLight inspired by OpenLight https://github.com/icamgo/noduino-sdk @@ -79,127 +99,134 @@ extern "C" { void os_delay_us(unsigned int); } -uint8_t sl_pdi; -uint8_t sl_pdcki; +uint8_t light_pdi_pin; +uint8_t light_pdcki_pin; -void sl_di_pulse(uint8_t times) +void LightDiPulse(uint8_t times) { for (uint8_t i = 0; i < times; i++) { - digitalWrite(sl_pdi, HIGH); - digitalWrite(sl_pdi, LOW); + digitalWrite(light_pdi_pin, HIGH); + digitalWrite(light_pdi_pin, LOW); } } -void sl_dcki_pulse(uint8_t times) +void LightDckiPulse(uint8_t times) { for (uint8_t i = 0; i < times; i++) { - digitalWrite(sl_pdcki, HIGH); - digitalWrite(sl_pdcki, LOW); + digitalWrite(light_pdcki_pin, HIGH); + digitalWrite(light_pdcki_pin, LOW); } } -void sl_my92x1_write(uint8_t data) +void LightMy92x1Write(uint8_t data) { - for (uint8_t i = 0; i < 4; i++) { // Send 8bit Data - digitalWrite(sl_pdcki, LOW); - digitalWrite(sl_pdi, (data & 0x80)); - digitalWrite(sl_pdcki, HIGH); + for (uint8_t i = 0; i < 4; i++) { // Send 8bit Data + digitalWrite(light_pdcki_pin, LOW); + digitalWrite(light_pdi_pin, (data & 0x80)); + digitalWrite(light_pdcki_pin, HIGH); data = data << 1; - digitalWrite(sl_pdi, (data & 0x80)); - digitalWrite(sl_pdcki, LOW); - digitalWrite(sl_pdi, LOW); + digitalWrite(light_pdi_pin, (data & 0x80)); + digitalWrite(light_pdcki_pin, LOW); + digitalWrite(light_pdi_pin, LOW); data = data << 1; } } -void sl_my92x1_init() +void LightMy92x1Init() { - uint8_t chips = sfl_flg -3; // 1 (AiLight) or 2 (Sonoff B1) + uint8_t chips = light_type -11; // 1 (AiLight) or 2 (Sonoff B1) - sl_dcki_pulse(chips * 32); // Clear all duty register - os_delay_us(12); // TStop > 12us. + LightDckiPulse(chips * 32); // Clear all duty register + os_delay_us(12); // TStop > 12us. // Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12 // pulse's rising edge convert to command mode. - sl_di_pulse(12); - os_delay_us(12); // Delay >12us, begin send CMD data - for (uint8_t n = 0; n < chips; n++) { // Send CMD data - sl_my92x1_write(0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM + LightDiPulse(12); + os_delay_us(12); // Delay >12us, begin send CMD data + for (uint8_t n = 0; n < chips; n++) { // Send CMD data + LightMy92x1Write(0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM } - os_delay_us(12); // TStart > 12us. Delay 12 us. + os_delay_us(12); // TStart > 12us. Delay 12 us. // Send 16 DI pulse, at 14 pulse's falling edge store CMD data, and // at 16 pulse's falling edge convert to duty mode. - sl_di_pulse(16); - os_delay_us(12); // TStop > 12us. + LightDiPulse(16); + os_delay_us(12); // TStop > 12us. } -void sl_my92x1_duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c) +void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c) { uint8_t channels[2] = { 4, 6 }; - - uint8_t didx = sfl_flg -4; // 0 or 1 - + uint8_t didx = light_type -12; // 0 or 1 uint8_t duty[2][6] = {{ duty_r, duty_g, duty_b, duty_w, 0, 0 }, // Definition for RGBW channels { duty_w, duty_c, 0, duty_g, duty_r, duty_b }}; // Definition for RGBWC channels - os_delay_us(12); // TStop > 12us. + os_delay_us(12); // TStop > 12us. for (uint8_t channel = 0; channel < channels[didx]; channel++) { - sl_my92x1_write(duty[didx][channel]); // Send 8bit Data + LightMy92x1Write(duty[didx][channel]); // Send 8bit Data } - os_delay_us(12); // TStart > 12us. Ready for send DI pulse. - sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. - os_delay_us(12); // TStop > 12us. + os_delay_us(12); // TStart > 12us. Ready for send DI pulse. + LightDiPulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. + os_delay_us(12); // TStop > 12us. } /********************************************************************************************/ -void sl_init(void) +void LightInit(void) { - if (sfl_flg < 3) { - if (!my_module.gp.io[4]) { - pinMode(4, OUTPUT); // Stop floating outputs - digitalWrite(4, LOW); + uint8_t max_scheme = LS_MAX -1; + + if (light_type < LT_PWM6) { // PWM + for (byte i = 0; i < light_type; i++) { + Settings.pwm_value[i] = 0; // Disable direct PWM control } - if (!my_module.gp.io[5]) { - pinMode(5, OUTPUT); // Stop floating outputs - digitalWrite(5, LOW); + if (LT_PWM1 == light_type) { + Settings.light_color[0] = 255; // One PWM channel only supports Dimmer but needs max color } - if (!my_module.gp.io[14]) { - pinMode(14, OUTPUT); // Stop floating outputs - digitalWrite(14, LOW); + if (SONOFF_LED == Settings.module) { // Fix Sonoff Led instabilities + if (!my_module.gp.io[4]) { + pinMode(4, OUTPUT); // Stop floating outputs + digitalWrite(4, LOW); + } + if (!my_module.gp.io[5]) { + pinMode(5, OUTPUT); // Stop floating outputs + digitalWrite(5, LOW); + } + if (!my_module.gp.io[14]) { + pinMode(14, OUTPUT); // Stop floating outputs + digitalWrite(14, LOW); + } } - sysCfg.pwmvalue[0] = 0; // We use dimmer / led_color - if (2 == sfl_flg) { - sysCfg.pwmvalue[1] = 0; // We use led_color - } - sysCfg.led_scheme = 0; } #ifdef USE_WS2812 // ************************************************************************ - else if (3 == sfl_flg) { - ws2812_init(); - if (1 == sysCfg.led_scheme) { - sysCfg.led_scheme = 0; - } + else if (LT_WS2812 == light_type) { + Ws2812Init(); + max_scheme = LS_MAX +7; } #endif // USE_WS2812 ************************************************************************ else { - sl_pdi = pin[GPIO_DI]; - sl_pdcki = pin[GPIO_DCKI]; + light_pdi_pin = pin[GPIO_DI]; + light_pdcki_pin = pin[GPIO_DCKI]; - pinMode(sl_pdi, OUTPUT); - pinMode(sl_pdcki, OUTPUT); - digitalWrite(sl_pdi, LOW); - digitalWrite(sl_pdcki, LOW); + pinMode(light_pdi_pin, OUTPUT); + pinMode(light_pdcki_pin, OUTPUT); + digitalWrite(light_pdi_pin, LOW); + digitalWrite(light_pdcki_pin, LOW); - sl_my92x1_init(); - sysCfg.led_scheme = 0; + LightMy92x1Init(); } - sl_power = 0; - sl_any = 0; - sl_wakeupActive = 0; + light_subtype = light_type &7; + if (light_subtype < LST_RGB) { + max_scheme = LS_POWER; + } + if ((LS_WAKEUP == Settings.light_scheme) || (Settings.light_scheme > max_scheme)) { + Settings.light_scheme = LS_POWER; + } + light_power = 0; + light_update = 1; + light_wakeup_active = 0; } -void sl_setColorTemp(uint16_t ct) +void LightSetColorTemp(uint16_t ct) { /* Color Temperature (https://developers.meethue.com/documentation/core-concepts) * @@ -212,207 +239,308 @@ void sl_setColorTemp(uint16_t ct) } uint16_t icold = (100 * (347 - my_ct)) / 136; uint16_t iwarm = (100 * my_ct) / 136; - if (5 == sfl_flg) { - sysCfg.led_color[0] = 0; - sysCfg.led_color[1] = 0; - sysCfg.led_color[2] = 0; - sysCfg.led_color[3] = (uint8_t)icold; - sysCfg.led_color[4] = (uint8_t)iwarm; + if (LST_RGBWC == light_subtype) { + Settings.light_color[0] = 0; + Settings.light_color[1] = 0; + Settings.light_color[2] = 0; + Settings.light_color[3] = (uint8_t)icold; + Settings.light_color[4] = (uint8_t)iwarm; } else { - sysCfg.led_color[0] = (uint8_t)icold; - sysCfg.led_color[1] = (uint8_t)iwarm; + Settings.light_color[0] = (uint8_t)icold; + Settings.light_color[1] = (uint8_t)iwarm; } } -uint16_t sl_getColorTemp() +uint16_t LightGetColorTemp() { uint8_t ct_idx = 0; - if (5 == sfl_flg) { + if (LST_RGBWC == light_subtype) { ct_idx = 3; } - uint16_t my_ct = sysCfg.led_color[ct_idx +1]; + uint16_t my_ct = Settings.light_color[ct_idx +1]; if (my_ct > 0) { return ((my_ct * 136) / 100) + 154; } else { - my_ct = sysCfg.led_color[ct_idx]; + my_ct = Settings.light_color[ct_idx]; return 499 - ((my_ct * 136) / 100); } } -void sl_setDim(uint8_t myDimmer) +void LightSetDimmer(uint8_t myDimmer) { float temp; - if ((1 == sfl_flg) && (100 == myDimmer)) { - myDimmer = 99; // BN-SZ01 starts flickering at dimmer = 100 + if ((SONOFF_BN == Settings.module) && (100 == myDimmer)) { + myDimmer = 99; // BN-SZ01 starts flickering at dimmer = 100 } - float newDim = 100 / (float)myDimmer; - for (byte i = 0; i < sfl_flg; i++) { - temp = (float)sysCfg.led_color[i] / newDim; - sl_dcolor[i] = (uint8_t)temp; + float dimmer = 100 / (float)myDimmer; + for (byte i = 0; i < light_subtype; i++) { + temp = (float)Settings.light_color[i] / dimmer; + light_current_color[i] = (uint8_t)temp; } } -void sl_setColor() +void LightSetColor() { uint8_t highest = 0; - float temp; - for (byte i = 0; i < sfl_flg; i++) { - if (highest < sl_dcolor[i]) { - highest = sl_dcolor[i]; + for (byte i = 0; i < light_subtype; i++) { + if (highest < light_current_color[i]) { + highest = light_current_color[i]; } } float mDim = (float)highest / 2.55; - sysCfg.led_dimmer[0] = (uint8_t)mDim; - float newDim = 100 / mDim; - for (byte i = 0; i < sfl_flg; i++) { - temp = (float)sl_dcolor[i] * newDim; - sysCfg.led_color[i] = (uint8_t)temp; + Settings.light_dimmer = (uint8_t)mDim; + float dimmer = 100 / mDim; + for (byte i = 0; i < light_subtype; i++) { + float temp = (float)light_current_color[i] * dimmer; + Settings.light_color[i] = (uint8_t)temp; } } -char* sl_getColor(char* scolor) +char* LightGetColor(uint8_t type, char* scolor) { - sl_setDim(sysCfg.led_dimmer[0]); + LightSetDimmer(Settings.light_dimmer); scolor[0] = '\0'; - for (byte i = 0; i < sfl_flg; i++) { - snprintf_P(scolor, 11, PSTR("%s%02X"), scolor, sl_dcolor[i]); + for (byte i = 0; i < light_subtype; i++) { + if (!type && Settings.flag.decimal_text) { + snprintf_P(scolor, 25, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", light_current_color[i]); + } else { + snprintf_P(scolor, 25, PSTR("%s%02X"), scolor, light_current_color[i]); + } } return scolor; } -void sl_prepPower() +void LightPowerOn() { - char scolor[11]; - -// do_cmnd_power(index, (sysCfg.led_dimmer[0]>0)); - if (sysCfg.led_dimmer[0] && !(sl_power)) { - do_cmnd_power(Maxdevice, 7); // No publishPowerState + if (Settings.light_dimmer && !(light_power)) { + ExecuteCommandPower(devices_present, 1); } - else if (!sysCfg.led_dimmer[0] && sl_power) { - do_cmnd_power(Maxdevice, 6); // No publishPowerState +} + +void LightPreparePower() +{ + char scolor[25]; + char scommand[16]; + + if (Settings.light_dimmer && !(light_power)) { + ExecuteCommandPower(devices_present, 7); // No publishPowerState + } + else if (!Settings.light_dimmer && light_power) { + ExecuteCommandPower(devices_present, 6); // No publishPowerState } #ifdef USE_DOMOTICZ -// mqtt_publishDomoticzPowerState(1); - domoticz_updatePowerState(Maxdevice); + DomoticzUpdatePowerState(devices_present); #endif // USE_DOMOTICZ - if (sfl_flg > 1) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_RSLT_POWER "\":\"%s\", \"" D_CMND_DIMMER "\":%d, \"" D_CMND_COLOR "\":\"%s\"}"), - getStateText(sl_power), sysCfg.led_dimmer[0], sl_getColor(scolor)); + + GetPowerDevice(scommand, devices_present, sizeof(scommand)); + if (light_subtype > LST_SINGLE) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\", \"" D_CMND_DIMMER "\":%d, \"" D_CMND_COLOR "\":\"%s\"}"), + scommand, GetStateText(light_power), Settings.light_dimmer, LightGetColor(0, scolor)); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_RSLT_POWER "\":\"%s\", \"" D_CMND_DIMMER "\":%d}"), - getStateText(sl_power), sysCfg.led_dimmer[0]); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\", \"" D_CMND_DIMMER "\":%d}"), + scommand, GetStateText(light_power), Settings.light_dimmer); } } -void sl_setPower(uint8_t mpower) +void LightFade() { - sl_power = ((mpower & (0x01 << (Maxdevice -1))) != 0); - if (sl_wakeupActive) { - sl_wakeupActive--; + if (0 == Settings.light_fade) { + for (byte i = 0; i < light_subtype; i++) { + light_new_color[i] = light_current_color[i]; + } + } else { + uint8_t shift = Settings.light_speed; + if (Settings.light_speed > 6) { + shift = (strip_timer_counter % (Settings.light_speed -6)) ? 0 : 8; + } + if (shift) { + for (byte i = 0; i < light_subtype; i++) { + if (light_new_color[i] != light_current_color[i]) { + if (light_new_color[i] < light_current_color[i]) { + light_new_color[i] += ((light_current_color[i] - light_new_color[i]) >> shift) +1; + } + if (light_new_color[i] > light_current_color[i]) { + light_new_color[i] -= ((light_new_color[i] - light_current_color[i]) >> shift) +1; + } + } + } + } } - if (sl_power) { - sl_any = 1; - } - sl_animate(); } -void sl_animate() +void LightWheel(uint8_t wheel_pos) +{ + wheel_pos = 255 - wheel_pos; + if (wheel_pos < 85) { + light_entry_color[0] = 255 - wheel_pos * 3; + light_entry_color[1] = 0; + light_entry_color[2] = wheel_pos * 3; + } else if (wheel_pos < 170) { + wheel_pos -= 85; + light_entry_color[0] = 0; + light_entry_color[1] = wheel_pos * 3; + light_entry_color[2] = 255 - wheel_pos * 3; + } else { + wheel_pos -= 170; + light_entry_color[0] = wheel_pos * 3; + light_entry_color[1] = 255 - wheel_pos * 3; + light_entry_color[2] = 0; + } + light_entry_color[3] = 0; + light_entry_color[4] = 0; + float dimmer = 100 / (float)Settings.light_dimmer; + for (byte i = 0; i < LST_RGB; i++) { + float temp = (float)light_entry_color[i] / dimmer; + light_entry_color[i] = (uint8_t)temp; + } +} + +void LightCycleColor(int8_t direction) +{ + if (strip_timer_counter % (Settings.light_speed * 2)) { + return; + } + light_wheel += direction; + LightWheel(light_wheel); + memcpy(light_new_color, light_entry_color, sizeof(light_new_color)); +} + +void LightRandomColor() +{ + uint8_t light_update = 0; + for (byte i = 0; i < LST_RGB; i++) { + if (light_new_color[i] != light_current_color[i]) { + light_update = 1; + } + } + if (!light_update) { + light_wheel = random(255); + LightWheel(light_wheel); + memcpy(light_current_color, light_entry_color, sizeof(light_current_color)); + } + LightFade(); +} + +void LightSetPower(uint8_t mpower) +{ + light_power = mpower; + if (light_wakeup_active) { + light_wakeup_active--; + } + if (light_power) { + light_update = 1; + } + LightAnimate(); +} + +void LightAnimate() { -// {"Wakeup":"Done"} - uint8_t fadeValue; uint8_t cur_col[5]; + uint16_t light_still_on; - stripTimerCntr++; - if (!sl_power) { // Power Off - sleep = sysCfg.sleep; - stripTimerCntr = 0; - for (byte i = 0; i < sfl_flg; i++) { - sl_tcolor[i] = 0; + strip_timer_counter++; + if (!light_power) { // Power Off + sleep = Settings.sleep; + strip_timer_counter = 0; + for (byte i = 0; i < light_subtype; i++) { + light_still_on += light_new_color[i]; + } + if (light_still_on && Settings.light_fade && (Settings.light_scheme < LS_MAX)) { + uint8_t speed = Settings.light_speed; + if (speed > 6) { + speed = 6; + } + for (byte i = 0; i < light_subtype; i++) { + if (light_new_color[i] > 0) { + light_new_color[i] -= (light_new_color[i] >> speed) +1; + } + } + } else { + for (byte i = 0; i < light_subtype; i++) { + light_new_color[i] = 0; + } } } else { sleep = 0; - switch (sysCfg.led_scheme) { - case 0: // Power On - sl_setDim(sysCfg.led_dimmer[0]); // Power On - if (0 == sysCfg.led_fade) { - for (byte i = 0; i < sfl_flg; i++) { - sl_tcolor[i] = sl_dcolor[i]; - } - } else { - for (byte i = 0; i < sfl_flg; i++) { - if (sl_tcolor[i] != sl_dcolor[i]) { - if (sl_tcolor[i] < sl_dcolor[i]) { - sl_tcolor[i] += ((sl_dcolor[i] - sl_tcolor[i]) >> sysCfg.led_speed) +1; - } - if (sl_tcolor[i] > sl_dcolor[i]) { - sl_tcolor[i] -= ((sl_tcolor[i] - sl_dcolor[i]) >> sysCfg.led_speed) +1; - } - } - } - } + switch (Settings.light_scheme) { + case LS_POWER: + LightSetDimmer(Settings.light_dimmer); + LightFade(); break; - case 1: // Power On using wake up duration - if (2 == sl_wakeupActive) { - sl_wakeupActive = 1; - for (byte i = 0; i < sfl_flg; i++) { - sl_tcolor[i] = 0; + case LS_WAKEUP: + if (2 == light_wakeup_active) { + light_wakeup_active = 1; + for (byte i = 0; i < light_subtype; i++) { + light_new_color[i] = 0; } - sl_wakeupCntr = 0; - sl_wakeupDimmer = 0; + light_wakeup_counter = 0; + light_wakeup_dimmer = 0; } - sl_wakeupCntr++; - if (sl_wakeupCntr > ((sysCfg.led_wakeup * STATES) / sysCfg.led_dimmer[0])) { - sl_wakeupCntr = 0; - sl_wakeupDimmer++; - if (sl_wakeupDimmer <= sysCfg.led_dimmer[0]) { - sl_setDim(sl_wakeupDimmer); - for (byte i = 0; i < sfl_flg; i++) { - sl_tcolor[i] = sl_dcolor[i]; + light_wakeup_counter++; + if (light_wakeup_counter > ((Settings.light_wakeup * STATES) / Settings.light_dimmer)) { + light_wakeup_counter = 0; + light_wakeup_dimmer++; + if (light_wakeup_dimmer <= Settings.light_dimmer) { + LightSetDimmer(light_wakeup_dimmer); + for (byte i = 0; i < light_subtype; i++) { + light_new_color[i] = light_current_color[i]; } } else { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WAKEUP "\":\"" D_DONE "\"}")); - mqtt_publish_topic_P(2, PSTR(D_CMND_WAKEUP)); - sl_wakeupActive = 0; - sysCfg.led_scheme = 0; + MqttPublishPrefixTopic_P(2, PSTR(D_CMND_WAKEUP)); + light_wakeup_active = 0; + Settings.light_scheme = LS_POWER; } } break; + case LS_CYCLEUP: + LightCycleColor(1); + break; + case LS_CYCLEDN: + LightCycleColor(-1); + break; + case LS_RANDOM: + LightRandomColor(); + break; #ifdef USE_WS2812 // ************************************************************************ default: - if (3 == sfl_flg) { - ws2812_showScheme(sysCfg.led_scheme -2); + if (LT_WS2812 == light_type) { + Ws2812ShowScheme(Settings.light_scheme -LS_MAX); } #endif // USE_WS2812 ************************************************************************ } } - if ((sysCfg.led_scheme < 2) || !sl_power) { - for (byte i = 0; i < sfl_flg; i++) { - if (sl_lcolor[i] != sl_tcolor[i]) { - sl_any = 1; + if ((Settings.light_scheme < LS_MAX) || !light_power) { + for (byte i = 0; i < light_subtype; i++) { + if (light_last_color[i] != light_new_color[i]) { + light_update = 1; } } - if (sl_any) { - sl_any = 0; - for (byte i = 0; i < sfl_flg; i++) { - sl_lcolor[i] = sl_tcolor[i]; - cur_col[i] = (sysCfg.led_table) ? ledTable[sl_lcolor[i]] : sl_lcolor[i]; - if (sfl_flg < 3) { + if (light_update) { + light_update = 0; + for (byte i = 0; i < light_subtype; i++) { + light_last_color[i] = light_new_color[i]; + cur_col[i] = (Settings.light_correction) ? ledTable[light_last_color[i]] : light_last_color[i]; + if (light_type < LT_PWM6) { if (pin[GPIO_PWM1 +i] < 99) { - analogWrite(pin[GPIO_PWM1 +i], cur_col[i] * (PWM_RANGE / 255)); + uint16_t curcol = cur_col[i] * (Settings.pwm_range / 255); +// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "Cur_Col%d %d, CurCol %d"), i, cur_col[i], curcol); +// AddLog(LOG_LEVEL_DEBUG); + analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - curcol : curcol); } } } #ifdef USE_WS2812 // ************************************************************************ - if (3 == sfl_flg) { - ws2812_setColor(0, cur_col[0], cur_col[1], cur_col[2]); + if (LT_WS2812 == light_type) { + Ws2812SetColor(0, cur_col[0], cur_col[1], cur_col[2]); } #endif // USE_ES2812 ************************************************************************ - if (sfl_flg > 3) { - sl_my92x1_duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); + if (light_type > LT_WS2812) { + LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); } } } @@ -422,53 +550,53 @@ void sl_animate() * Hue support \*********************************************************************************************/ -float sl_Hue = 0.0; -float sl_Sat = 0.0; -float sl_Bri = 0.0; +float light_hue = 0.0; +float light_saturation = 0.0; +float light_brightness = 0.0; -void sl_rgb2hsb() +void LightRgbToHsb() { - sl_setDim(sysCfg.led_dimmer[0]); + LightSetDimmer(Settings.light_dimmer); // convert colors to float between (0.0 - 1.0) - float r = sl_dcolor[0] / 255.0f; - float g = sl_dcolor[1] / 255.0f; - float b = sl_dcolor[2] / 255.0f; + float r = light_current_color[0] / 255.0f; + float g = light_current_color[1] / 255.0f; + float b = light_current_color[2] / 255.0f; float max = (r > g && r > b) ? r : (g > b) ? g : b; float min = (r < g && r < b) ? r : (g < b) ? g : b; float d = max - min; - sl_Hue = 0.0; - sl_Bri = max; - sl_Sat = (0.0f == sl_Bri) ? 0 : (d / sl_Bri); + light_hue = 0.0; + light_brightness = max; + light_saturation = (0.0f == light_brightness) ? 0 : (d / light_brightness); if (d != 0.0f) { if (r == max) { - sl_Hue = (g - b) / d + (g < b ? 6.0f : 0.0f); + light_hue = (g - b) / d + (g < b ? 6.0f : 0.0f); } else if (g == max) { - sl_Hue = (b - r) / d + 2.0f; + light_hue = (b - r) / d + 2.0f; } else { - sl_Hue = (r - g) / d + 4.0f; + light_hue = (r - g) / d + 4.0f; } - sl_Hue /= 6.0f; + light_hue /= 6.0f; } } -void sl_hsb2rgb() +void LightHsbToRgb() { float r; float g; float b; - float h = sl_Hue; - float s = sl_Sat; - float v = sl_Bri; + float h = light_hue; + float s = light_saturation; + float v = light_brightness; - if (0.0f == sl_Sat) { - r = g = b = v; // achromatic or black + if (0.0f == light_saturation) { + r = g = b = v; // Achromatic or black } else { if (h < 0.0f) { h += 1.0f; @@ -516,80 +644,69 @@ void sl_hsb2rgb() } } - sl_dcolor[0] = (uint8_t)(r * 255.0f); - sl_dcolor[1] = (uint8_t)(g * 255.0f); - sl_dcolor[2] = (uint8_t)(b * 255.0f); + light_current_color[0] = (uint8_t)(r * 255.0f); + light_current_color[1] = (uint8_t)(g * 255.0f); + light_current_color[2] = (uint8_t)(b * 255.0f); } /********************************************************************************************/ -void sl_replaceHSB(String *response) +void LightReplaceHsb(String *response) { - if (sfl_flg > 2) { - sl_rgb2hsb(); - response->replace("{h}", String((uint16_t)(65535.0f * sl_Hue))); - response->replace("{s}", String((uint8_t)(254.0f * sl_Sat))); - response->replace("{b}", String((uint8_t)(254.0f * sl_Bri))); + if (light_subtype > LST_COLDWARM) { + LightRgbToHsb(); + response->replace("{h}", String((uint16_t)(65535.0f * light_hue))); + response->replace("{s}", String((uint8_t)(254.0f * light_saturation))); + response->replace("{b}", String((uint8_t)(254.0f * light_brightness))); } else { response->replace("{h}", "0"); response->replace("{s}", "0"); -// response->replace("{b}", String((uint8_t)(2.54f * (float)sysCfg.led_dimmer[0]))); - response->replace("{b}", String((uint8_t)(0.01f * (float)sysCfg.led_dimmer[0]))); +// response->replace("{b}", String((uint8_t)(2.54f * (float)Settings.light_dimmer))); + response->replace("{b}", String((uint8_t)(0.01f * (float)Settings.light_dimmer))); } } -void sl_getHSB(float *hue, float *sat, float *bri) +void LightGetHsb(float *hue, float *sat, float *bri) { - if (sfl_flg > 2) { - sl_rgb2hsb(); - *hue = sl_Hue; - *sat = sl_Sat; - *bri = sl_Bri; + if (light_subtype > LST_COLDWARM) { + LightRgbToHsb(); + *hue = light_hue; + *sat = light_saturation; + *bri = light_brightness; } else { *hue = 0; *sat = 0; -// *bri = (2.54f * (float)sysCfg.led_dimmer[0]); - *bri = (0.01f * (float)sysCfg.led_dimmer[0]); +// *bri = (2.54f * (float)Settings.light_dimmer); + *bri = (0.01f * (float)Settings.light_dimmer); } } -void sl_setHSB(float hue, float sat, float bri, uint16_t ct) +void LightSetHsb(float hue, float sat, float bri, uint16_t ct) { -/* - char stemp1[10]; - char stemp2[10]; - char stemp3[10]; - dtostrfi(hue, 3, stemp1); - dtostrfi(sat, 3, stemp2); - dtostrfi(bri, 3, stemp3); - snprintf_P(log_data, sizeof(log_data), PSTR("HUE: Set Hue %s, Sat %s, Bri %s, Ct %d"), stemp1, stemp2, stemp3, ct); - addLog(LOG_LEVEL_DEBUG); -*/ - - if (sfl_flg > 2) { - if ((5 == sfl_flg) && (ct > 0)) { - sl_setColorTemp(ct); + if (light_subtype > LST_COLDWARM) { + if ((LST_RGBWC == light_subtype) && (ct > 0)) { + LightSetColorTemp(ct); } else { - sl_Hue = hue; - sl_Sat = sat; - sl_Bri = bri; - sl_hsb2rgb(); - sl_setColor(); + light_hue = hue; + light_saturation = sat; + light_brightness = bri; + LightHsbToRgb(); + LightSetColor(); } - sl_prepPower(); - mqtt_publish_topic_P(5, PSTR(D_CMND_COLOR)); + LightPreparePower(); + MqttPublishPrefixTopic_P(5, PSTR(D_CMND_COLOR)); } else { uint8_t tmp = (uint8_t)(bri * 100); - sysCfg.led_dimmer[0] = tmp; - if (2 == sfl_flg) { + Settings.light_dimmer = tmp; + if (LST_COLDWARM == light_subtype) { if (ct > 0) { - sl_setColorTemp(ct); + LightSetColorTemp(ct); } - sl_prepPower(); - mqtt_publish_topic_P(5, PSTR(D_CMND_COLOR)); + LightPreparePower(); + MqttPublishPrefixTopic_P(5, PSTR(D_CMND_COLOR)); } else { - sl_prepPower(); - mqtt_publish_topic_P(5, PSTR(D_CMND_DIMMER)); + LightPreparePower(); + MqttPublishPrefixTopic_P(5, PSTR(D_CMND_DIMMER)); } } } @@ -598,149 +715,205 @@ void sl_setHSB(float hue, float sat, float bri, uint16_t ct) * Commands \*********************************************************************************************/ -boolean sl_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload) +boolean LightColorEntry(char *buffer, uint8_t buffer_length) { + char scolor[10]; + char *p; + char *str; + uint8_t entry_type = 0; // Invalid + + if (buffer[0] == '#') { // Optional hexadecimal entry + buffer++; + buffer_length--; + } + if (strstr(buffer, ",")) { // Decimal entry + int8_t i = 0; + for (str = strtok_r(buffer, ",", &p); str && i < 6; str = strtok_r(NULL, ",", &p)) { + if (i < 5) { + light_entry_color[i++] = atoi(str); + } + } + entry_type = (light_subtype == i) ? 2 : 0; // Decimal + } + else if ((2 * light_subtype) == buffer_length) { // Hexadecimal entry + for (byte i = 0; i < light_subtype; i++) { + strlcpy(scolor, buffer + (i *2), 3); + light_entry_color[i] = (uint8_t)strtol(scolor, &p, 16); + } + entry_type = 1; // Hexadecimal + } + if (entry_type) { + Settings.flag.decimal_text = entry_type -1; + } + return (entry_type); +} + +/********************************************************************************************/ + +boolean LightCommand(char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload) +{ + char command [CMDSZ]; boolean serviced = true; boolean coldim = false; - char scolor[11]; - char *p; + boolean valid_entry = false; + char scolor[25]; - if ((sfl_flg > 1) && !strcasecmp_P(type, PSTR(D_CMND_COLOR))) { - if (dataBuf[0] == '#') { - dataBuf++; - data_len--; - } - if ((2 * sfl_flg) == data_len) { - for (byte i = 0; i < sfl_flg; i++) { - strlcpy(scolor, dataBuf + (i *2), 3); - sl_dcolor[i] = (uint8_t)strtol(scolor, &p, 16); + int command_code = GetCommandCode(command, sizeof(command), type, kLightCommands); + if ((CMND_COLOR == command_code) && (light_subtype > LST_SINGLE) && (index > 0) && (index <= 4)) { + if (data_len > 0) { + valid_entry = LightColorEntry(dataBuf, data_len); + if (valid_entry) { + if (1 == index) { // Color(1) +// for (byte i = 0; i < light_subtype; i++) { +// light_current_color[i] = light_entry_color[i]; +// } + memcpy(light_current_color, light_entry_color, sizeof(light_current_color)); + LightSetColor(); + Settings.light_scheme = 0; + coldim = true; + } else { // Color2, 3 and 4 + for (byte i = 0; i < LST_RGB; i++) { + Settings.ws_color[index -2][i] = light_entry_color[i]; + } + } } - sl_setColor(); - coldim = true; - } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_COLOR "\":\"%s\"}"), sl_getColor(scolor)); + } + if (!valid_entry && (1 == index)) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"), command, LightGetColor(0, scolor)); + } + if (index > 1) { + scolor[0] = '\0'; + for (byte i = 0; i < LST_RGB; i++) { + if (Settings.flag.decimal_text) { + snprintf_P(scolor, 25, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.ws_color[index -2][i]); + } else { + snprintf_P(scolor, 25, PSTR("%s%02X"), scolor, Settings.ws_color[index -2][i]); + } + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, scolor); } } #ifdef USE_WS2812 // *********************************************************************** - else if ((3 == sfl_flg) && !strcasecmp_P(type, PSTR(D_CMND_LED)) && (index > 0) && (index <= sysCfg.led_pixels)) { - if (dataBuf[0] == '#') { - dataBuf++; - data_len--; - } - uint8_t sl_ledcolor[3]; - if ((2 * sfl_flg) == data_len) { - for (byte i = 0; i < sfl_flg; i++) { - strlcpy(scolor, dataBuf + (i *2), 3); - sl_ledcolor[i] = (uint8_t)strtol(scolor, &p, 16); + else if ((CMND_LED == command_code) && (LT_WS2812 == light_type) && (index > 0) && (index <= Settings.light_pixels)) { + if (data_len > 0) { + if (LightColorEntry(dataBuf, data_len)) { + Ws2812SetColor(index, light_entry_color[0], light_entry_color[1], light_entry_color[2]); } - ws2812_setColor(index, sl_ledcolor[0], sl_ledcolor[1], sl_ledcolor[2]); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_LED "%d\":\"%s\"}"), index, ws2812_getColor(index, scolor)); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Ws2812GetColor(index, scolor)); } - else if ((3 == sfl_flg) && !strcasecmp_P(type, PSTR(D_CMND_PIXELS))) { + else if ((CMND_PIXELS == command_code) && (LT_WS2812 == light_type)) { if ((payload > 0) && (payload <= WS2812_MAX_LEDS)) { - sysCfg.led_pixels = payload; - ws2812_clear(); - sl_any = 1; + Settings.light_pixels = payload; + Ws2812Clear(); + light_update = 1; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_PIXELS "\":%d}"), sysCfg.led_pixels); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_pixels); } - else if ((3 == sfl_flg) && !strcasecmp_P(type, PSTR(D_CMND_WIDTH))) { - if ((payload >= 0) && (payload <= 4)) { - sysCfg.led_width = payload; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WIDTH "\":%d}"), sysCfg.led_width); - } - else if ((3 == sfl_flg) && !strcasecmp_P(type, PSTR(D_CMND_SCHEME))) { - if ((payload >= 0) && (payload <= 9)) { - sysCfg.led_scheme = payload; - if (1 == sysCfg.led_scheme) { - sl_wakeupActive = 3; + else if ((CMND_WIDTH == command_code) && (LT_WS2812 == light_type) && (index > 0) && (index <= 4)) { + if (1 == index) { + if ((payload >= 0) && (payload <= 4)) { + Settings.light_width = payload; } - do_cmnd_power(Maxdevice, 1); - stripTimerCntr = 0; + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_width); + } else { + if ((payload > 0) && (payload < 32)) { + Settings.ws_width[index -2] = payload; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, index, Settings.ws_width[index -2]); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_SCHEME "\":%d}"), sysCfg.led_scheme); } #endif // USE_WS2812 ************************************************************************ - else if (!strcasecmp_P(type, PSTR(D_CMND_WAKEUP))) { - if ((payload >= 0) && (payload <= 100)) { - sysCfg.led_dimmer[0] = payload; + else if ((CMND_SCHEME == command_code) && (light_subtype >= LST_RGB)) { + uint8_t max_scheme = (LT_WS2812 == light_type) ? LS_MAX +7 : LS_MAX -1; + if ((payload >= 0) && (payload <= max_scheme)) { + Settings.light_scheme = payload; + if (LS_WAKEUP == Settings.light_scheme) { + light_wakeup_active = 3; + } + LightPowerOn(); + strip_timer_counter = 0; } - sl_wakeupActive = 3; - sysCfg.led_scheme = 1; - do_cmnd_power(Maxdevice, 1); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WAKEUP "\":\"" D_STARTED "\"}")); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_scheme); } - else if (!strcasecmp_P(type, PSTR(D_CMND_COLORTEMPERATURE)) && ((2 == sfl_flg) || (5 == sfl_flg))) { // ColorTemp + else if (CMND_WAKEUP == command_code) { + if ((payload >= 0) && (payload <= 100)) { + Settings.light_dimmer = payload; + } + light_wakeup_active = 3; + Settings.light_scheme = LS_WAKEUP; + LightPowerOn(); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_STARTED); + } + else if ((CMND_COLORTEMPERATURE == command_code) && ((2 == light_subtype) || (5 == light_subtype))) { // ColorTemp if ((payload >= 153) && (payload <= 500)) { // https://developers.meethue.com/documentation/core-concepts - sl_setColorTemp(payload); + LightSetColorTemp(payload); coldim = true; } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_COLORTEMPERATURE "\":%d}"), sl_getColorTemp()); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, LightGetColorTemp()); } } - else if (!strcasecmp_P(type, PSTR(D_CMND_DIMMER))) { + else if (CMND_DIMMER == command_code) { if ((payload >= 0) && (payload <= 100)) { - sysCfg.led_dimmer[0] = payload; + Settings.light_dimmer = payload; coldim = true; } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DIMMER "\":%d}"), sysCfg.led_dimmer[0]); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_dimmer); } } - else if (!strcasecmp_P(type, PSTR(D_CMND_LEDTABLE))) { + else if (CMND_LEDTABLE == command_code) { if ((payload >= 0) && (payload <= 2)) { switch (payload) { case 0: // Off case 1: // On - sysCfg.led_table = payload; + Settings.light_correction = payload; break; case 2: // Toggle - sysCfg.led_table ^= 1; + Settings.light_correction ^= 1; break; } - sl_any = 1; + light_update = 1; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_LEDTABLE "\":\"%s\"}"), getStateText(sysCfg.led_table)); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.light_correction)); } - else if (!strcasecmp_P(type, PSTR(D_CMND_FADE))) { + else if (CMND_FADE == command_code) { switch (payload) { case 0: // Off case 1: // On - sysCfg.led_fade = payload; + Settings.light_fade = payload; break; case 2: // Toggle - sysCfg.led_fade ^= 1; + Settings.light_fade ^= 1; break; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_FADE "\":\"%s\"}"), getStateText(sysCfg.led_fade)); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.light_fade)); } - else if (!strcasecmp_P(type, PSTR(D_CMND_SPEED))) { // 1 - fast, 8 - slow - if ((payload > 0) && (payload <= 8)) { - sysCfg.led_speed = payload; + else if (CMND_SPEED == command_code) { // 1 - fast, 20 - very slow + if ((payload > 0) && (payload <= STATES)) { + Settings.light_speed = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_SPEED "\":%d}"), sysCfg.led_speed); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_speed); } - else if (!strcasecmp_P(type, PSTR(D_CMND_WAKEUPDURATION))) { + else if (CMND_WAKEUPDURATION == command_code) { if ((payload > 0) && (payload < 3001)) { - sysCfg.led_wakeup = payload; - sl_wakeupActive = 0; + Settings.light_wakeup = payload; + light_wakeup_active = 0; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WAKEUPDURATION "\":%d}"), sysCfg.led_wakeup); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, Settings.light_wakeup); } - else if (!strcasecmp_P(type, PSTR("UNDOCA"))) { // Theos legacy status - sl_getColor(scolor); + else if (CMND_UNDOCA == command_code) { // Theos legacy status + LightGetColor(1, scolor); scolor[6] = '\0'; // RGB only snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, %d, %d, %d, %d, %d"), - scolor, sysCfg.led_fade, sysCfg.led_table, sysCfg.led_scheme, sysCfg.led_speed, sysCfg.led_width); - mqtt_publish_topic_P(1, type); + scolor, Settings.light_fade, Settings.light_correction, Settings.light_scheme, Settings.light_speed, Settings.light_width); + MqttPublishPrefixTopic_P(1, type); mqtt_data[0] = '\0'; } else { serviced = false; // Unknown command } if (coldim) { - sl_prepPower(); + LightPreparePower(); } return serviced; } diff --git a/sonoff/xdrv_snfsc.ino b/sonoff/xdrv_snfsc.ino index c6ed4c767..5cd50e45b 100644 --- a/sonoff/xdrv_snfsc.ino +++ b/sonoff/xdrv_snfsc.ino @@ -55,29 +55,29 @@ uint16_t sc_value[5] = { 0 }; -void sc_send(const char *data) +void SonoffScSend(const char *data) { Serial.write(data); Serial.write('\x1B'); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SERIAL D_TRANSMIT " %s"), data); - addLog(LOG_LEVEL_DEBUG); + AddLog(LOG_LEVEL_DEBUG); } -void sc_init() +void SonoffScInit() { -// sc_send("AT+DEVCONFIG=\"uploadFreq\":1800"); - sc_send("AT+START"); -// sc_send("AT+STATUS"); +// SonoffScSend("AT+DEVCONFIG=\"uploadFreq\":1800"); + SonoffScSend("AT+START"); +// SonoffScSend("AT+STATUS"); } -void sc_rcvstat(char *rcvstat) +void SonoffScSerialInput(char *rcvstat) { char *p; char *str; uint16_t value[5] = { 0 }; snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SERIAL D_RECEIVED " %s"), rcvstat); - addLog(LOG_LEVEL_DEBUG); + AddLog(LOG_LEVEL_DEBUG); if (!strncasecmp_P(rcvstat, PSTR("AT+UPDATE="), 10)) { int8_t i = -1; @@ -91,13 +91,13 @@ void sc_rcvstat(char *rcvstat) sc_value[2] = (11 - sc_value[2]) * 10; // Invert light level sc_value[3] *= 10; sc_value[4] = (11 - sc_value[4]) * 10; // Invert dust level - sc_send("AT+SEND=ok"); + SonoffScSend("AT+SEND=ok"); } else { - sc_send("AT+SEND=fail"); + SonoffScSend("AT+SEND=fail"); } } else if (!strcasecmp_P(rcvstat, PSTR("AT+STATUS?"))) { - sc_send("AT+STATUS=4"); + SonoffScSend("AT+STATUS=4"); } } @@ -105,28 +105,28 @@ void sc_rcvstat(char *rcvstat) * Presentation \*********************************************************************************************/ -void sc_mqttPresent(uint8_t* djson) +void MqttShowSonoffSC(uint8_t* djson) { if (sc_value[0] > 0) { char stemp1[10]; char stemp2[10]; - float t = convertTemp(sc_value[1]); - dtostrfd(t, sysCfg.flag.temperature_resolution, stemp1); + float t = ConvertTemp(sc_value[1]); + dtostrfd(t, Settings.flag.temperature_resolution, stemp1); float h = sc_value[0]; - dtostrfd(h, sysCfg.flag.humidity_resolution, stemp2); + dtostrfd(h, Settings.flag.humidity_resolution, stemp2); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_TEMPERATURE "\":%s, \"" D_HUMIDITY "\":%s, \"" D_LIGHT "\":%d, \"" D_NOISE "\":%d, \"" D_AIRQUALITY "\":%d"), mqtt_data, stemp1, stemp2, sc_value[2], sc_value[3], sc_value[4]); *djson = 1; #ifdef USE_DOMOTICZ - domoticz_sensor2(stemp1, stemp2); - domoticz_sensor5(sc_value[2]); + DomoticzTempHumSensor(stemp1, stemp2); + DomoticzSensor(DZ_ILLUMINANCE, sc_value[2]); #endif // USE_DOMOTICZ } } #ifdef USE_WEBSERVER -String sc_webPresent() +String WebShowSonoffSc() { String page = ""; @@ -135,12 +135,12 @@ String sc_webPresent() char sensor[80]; char scstype[] = ""; - float t = convertTemp(sc_value[1]); - dtostrfi(t, sysCfg.flag.temperature_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, scstype, stemp, tempUnit()); + float t = ConvertTemp(sc_value[1]); + dtostrfi(t, Settings.flag.temperature_resolution, stemp); + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, scstype, stemp, TempUnit()); page += sensor; float h = sc_value[0]; - dtostrfi(h, sysCfg.flag.humidity_resolution, stemp); + dtostrfi(h, Settings.flag.humidity_resolution, stemp); snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, scstype, stemp); page += sensor; snprintf_P(sensor, sizeof(sensor), HTTP_SNS_LIGHT, scstype, sc_value[2]); diff --git a/sonoff/xdrv_wemohue.ino b/sonoff/xdrv_wemohue.ino index 8500f28dc..73b8d4f3a 100644 --- a/sonoff/xdrv_wemohue.ino +++ b/sonoff/xdrv_wemohue.ino @@ -25,11 +25,11 @@ #define UDP_BUFFER_SIZE 200 // Max UDP buffer size needed for M-SEARCH message -boolean udpConnected = false; +boolean udp_connected = false; -char packetBuffer[UDP_BUFFER_SIZE]; // buffer to hold incoming UDP packet +char packet_buffer[UDP_BUFFER_SIZE]; // buffer to hold incoming UDP packet IPAddress ipMulticast(239, 255, 255, 250); // Simple Service Discovery Protocol (SSDP) -uint32_t portMulticast = 1900; // Multicast address and port +uint32_t port_multicast = 1900; // Multicast address and port /*********************************************************************************************\ * WeMo UPNP support routines @@ -40,16 +40,16 @@ const char WEMO_MSEARCH[] PROGMEM = "CACHE-CONTROL: max-age=86400\r\n" "DATE: Fri, 15 Apr 2016 04:56:29 GMT\r\n" "EXT:\r\n" - "LOCATION: http://{r1}:80/setup.xml\r\n" + "LOCATION: http://{r1:80/setup.xml\r\n" "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" "01-NLS: b9200ebb-736d-4b93-bf03-835149d13983\r\n" "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n" "ST: urn:Belkin:device:**\r\n" - "USN: uuid:{r2}::urn:Belkin:device:**\r\n" + "USN: uuid:{r2::urn:Belkin:device:**\r\n" "X-User-Agent: redsonic\r\n" "\r\n"; -String wemo_serial() +String WemoSerialnumber() { char serial[16]; @@ -57,31 +57,31 @@ String wemo_serial() return String(serial); } -String wemo_UUID() +String WemoUuid() { char uuid[27]; - snprintf_P(uuid, sizeof(uuid), PSTR("Socket-1_0-%s"), wemo_serial().c_str()); + snprintf_P(uuid, sizeof(uuid), PSTR("Socket-1_0-%s"), WemoSerialnumber().c_str()); return String(uuid); } -void wemo_respondToMSearch() +void WemoRespondToMSearch() { char message[TOPSZ]; - if (portUDP.beginPacket(portUDP.remoteIP(), portUDP.remotePort())) { + if (PortUdp.beginPacket(PortUdp.remoteIP(), PortUdp.remotePort())) { String response = FPSTR(WEMO_MSEARCH); - response.replace("{r1}", WiFi.localIP().toString()); - response.replace("{r2}", wemo_UUID()); - portUDP.write(response.c_str()); - portUDP.endPacket(); + response.replace("{r1", WiFi.localIP().toString()); + response.replace("{r2", WemoUuid()); + PortUdp.write(response.c_str()); + PortUdp.endPacket(); snprintf_P(message, sizeof(message), PSTR(D_RESPONSE_SENT)); } else { snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE)); } snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPNP D_WEMO " %s " D_TO " %s:%d"), - message, portUDP.remoteIP().toString().c_str(), portUDP.remotePort()); - addLog(LOG_LEVEL_DEBUG); + message, PortUdp.remoteIP().toString().c_str(), PortUdp.remotePort()); + AddLog(LOG_LEVEL_DEBUG); } /*********************************************************************************************\ @@ -97,23 +97,23 @@ const char HUE_RESPONSE[] PROGMEM = "HOST: 239.255.255.250:1900\r\n" "CACHE-CONTROL: max-age=100\r\n" "EXT:\r\n" - "LOCATION: http://{r1}:80/description.xml\r\n" + "LOCATION: http://{r1:80/description.xml\r\n" "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.17.0\r\n" - "hue-bridgeid: {r2}\r\n"; + "hue-bridgeid: {r2\r\n"; const char HUE_ST1[] PROGMEM = "ST: upnp:rootdevice\r\n" - "USN: uuid:{r3}::upnp:rootdevice\r\n" + "USN: uuid:{r3::upnp:rootdevice\r\n" "\r\n"; const char HUE_ST2[] PROGMEM = - "ST: uuid:{r3}\r\n" - "USN: uuid:{r3}\r\n" + "ST: uuid:{r3\r\n" + "USN: uuid:{r3\r\n" "\r\n"; const char HUE_ST3[] PROGMEM = "ST: urn:schemas-upnp-org:device:basic:1\r\n" - "USN: uuid:{r3}\r\n" + "USN: uuid:{r3\r\n" "\r\n"; -String hue_bridgeid() +String HueBridgeId() { String temp = WiFi.macAddress(); temp.replace(":", ""); @@ -121,7 +121,7 @@ String hue_bridgeid() return bridgeid; // 5CCF7FFFFE139F3D } -String hue_serial() +String HueSerialnumber() { String serial = WiFi.macAddress(); serial.replace(":", ""); @@ -129,106 +129,106 @@ String hue_serial() return serial; // 5ccf7f139f3d } -String hue_UUID() +String HueUuid() { String uuid = F("f6543a06-da50-11ba-8d8f-"); - uuid += hue_serial(); + uuid += HueSerialnumber(); return uuid; // f6543a06-da50-11ba-8d8f-5ccf7f139f3d } -void hue_respondToMSearch() +void HueRespondToMSearch() { char message[TOPSZ]; - if (portUDP.beginPacket(portUDP.remoteIP(), portUDP.remotePort())) { + if (PortUdp.beginPacket(PortUdp.remoteIP(), PortUdp.remotePort())) { String response1 = FPSTR(HUE_RESPONSE); - response1.replace("{r1}", WiFi.localIP().toString()); - response1.replace("{r2}", hue_bridgeid()); + response1.replace("{r1", WiFi.localIP().toString()); + response1.replace("{r2", HueBridgeId()); String response = response1; response += FPSTR(HUE_ST1); - response.replace("{r3}", hue_UUID()); - portUDP.write(response.c_str()); - portUDP.endPacket(); + response.replace("{r3", HueUuid()); + PortUdp.write(response.c_str()); + PortUdp.endPacket(); response = response1; response += FPSTR(HUE_ST2); - response.replace("{r3}", hue_UUID()); - portUDP.write(response.c_str()); - portUDP.endPacket(); + response.replace("{r3", HueUuid()); + PortUdp.write(response.c_str()); + PortUdp.endPacket(); response = response1; response += FPSTR(HUE_ST3); - response.replace("{r3}", hue_UUID()); - portUDP.write(response.c_str()); - portUDP.endPacket(); + response.replace("{r3", HueUuid()); + PortUdp.write(response.c_str()); + PortUdp.endPacket(); snprintf_P(message, sizeof(message), PSTR(D_3_RESPONSE_PACKETS_SENT)); } else { snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE)); } snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPNP D_HUE " %s " D_TO " %s:%d"), - message, portUDP.remoteIP().toString().c_str(), portUDP.remotePort()); - addLog(LOG_LEVEL_DEBUG); + message, PortUdp.remoteIP().toString().c_str(), PortUdp.remotePort()); + AddLog(LOG_LEVEL_DEBUG); } /*********************************************************************************************\ * Belkin WeMo and Philips Hue bridge UDP multicast support \*********************************************************************************************/ -boolean UDP_Disconnect() +boolean UdpDisconnect() { - if (udpConnected) { + if (udp_connected) { WiFiUDP::stopAll(); - addLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_MULTICAST_DISABLED)); - udpConnected = false; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_MULTICAST_DISABLED)); + udp_connected = false; } - return udpConnected; + return udp_connected; } -boolean UDP_Connect() +boolean UdpConnect() { - if (!udpConnected) { - if (portUDP.beginMulticast(WiFi.localIP(), ipMulticast, portMulticast)) { - addLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_REJOINED)); - udpConnected = true; + if (!udp_connected) { + if (PortUdp.beginMulticast(WiFi.localIP(), ipMulticast, port_multicast)) { + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_REJOINED)); + udp_connected = true; } else { - addLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_JOIN_FAILED)); - udpConnected = false; + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_JOIN_FAILED)); + udp_connected = false; } } - return udpConnected; + return udp_connected; } -void pollUDP() +void PollUdp() { - if (udpConnected) { - if (portUDP.parsePacket()) { - int len = portUDP.read(packetBuffer, UDP_BUFFER_SIZE -1); + if (udp_connected) { + if (PortUdp.parsePacket()) { + int len = PortUdp.read(packet_buffer, UDP_BUFFER_SIZE -1); if (len > 0) { - packetBuffer[len] = 0; + packet_buffer[len] = 0; } - String request = packetBuffer; + String request = packet_buffer; -// addLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet received")); -// addLog_P(LOG_LEVEL_DEBUG_MORE, packetBuffer); +// AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet received")); +// AddLog_P(LOG_LEVEL_DEBUG_MORE, packet_buffer); if (request.indexOf("M-SEARCH") >= 0) { request.toLowerCase(); request.replace(" ", ""); -// addLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet received")); -// addLog_P(LOG_LEVEL_DEBUG_MORE, request.c_str()); +// AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet received")); +// AddLog_P(LOG_LEVEL_DEBUG_MORE, request.c_str()); - if ((EMUL_WEMO == sysCfg.flag.emulation) && (request.indexOf(F("urn:belkin:device:**")) > 0)) { - wemo_respondToMSearch(); + if ((EMUL_WEMO == Settings.flag.emulation) && (request.indexOf(F("urn:belkin:device:**")) > 0)) { + WemoRespondToMSearch(); } - else if ((EMUL_HUE == sysCfg.flag.emulation) && + else if ((EMUL_HUE == Settings.flag.emulation) && ((request.indexOf(F("st:urn:schemas-upnp-org:device:basic:1")) > 0) || (request.indexOf(F("st:upnp:rootdevice")) > 0) || (request.indexOf(F("st:ssdpsearch:all")) > 0) || (request.indexOf(F("st:ssdp:all")) > 0))) { - hue_respondToMSearch(); + HueRespondToMSearch(); } } } @@ -273,12 +273,12 @@ const char WEMO_SETUP_XML[] PROGMEM = "" "" "urn:Belkin:device:controllee:1" - "{x1}" + "{x1" "Belkin International Inc." "Sonoff Socket" "3.1415" - "uuid:{x2}" - "{x3}" + "uuid:{x2" + "{x3" "0" "" "" @@ -295,36 +295,36 @@ const char WEMO_SETUP_XML[] PROGMEM = /********************************************************************************************/ -void handleUPnPevent() +void HandleUpnpEvent() { - addLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); - String request = webServer->arg(0); + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); + String request = WebServer->arg(0); if (request.indexOf(F("State>1 0) { -// do_cmnd_power(1, 1); - do_cmnd_power(Maxdevice, 1); +// ExecuteCommandPower(1, 1); + ExecuteCommandPower(devices_present, 1); } if (request.indexOf(F("State>0 0) { -// do_cmnd_power(1, 0); - do_cmnd_power(Maxdevice, 0); +// ExecuteCommandPower(1, 0); + ExecuteCommandPower(devices_present, 0); } - webServer->send(200, FPSTR(HDR_CTYPE_PLAIN), ""); + WebServer->send(200, FPSTR(HDR_CTYPE_PLAIN), ""); } -void handleUPnPservice() +void HandleUpnpService() { - addLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_EVENT_SERVICE)); - webServer->send(200, FPSTR(HDR_CTYPE_PLAIN), FPSTR(WEMO_EVENTSERVICE_XML)); + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_EVENT_SERVICE)); + WebServer->send(200, FPSTR(HDR_CTYPE_PLAIN), FPSTR(WEMO_EVENTSERVICE_XML)); } -void handleUPnPsetupWemo() +void HandleUpnpSetupWemo() { - addLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_SETUP)); + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_SETUP)); String setup_xml = FPSTR(WEMO_SETUP_XML); - setup_xml.replace("{x1}", sysCfg.friendlyname[0]); - setup_xml.replace("{x2}", wemo_UUID()); - setup_xml.replace("{x3}", wemo_serial()); - webServer->send(200, FPSTR(HDR_CTYPE_XML), setup_xml); + setup_xml.replace("{x1", Settings.friendlyname[0]); + setup_xml.replace("{x2", WemoUuid()); + setup_xml.replace("{x3", WemoSerialnumber()); + WebServer->send(200, FPSTR(HDR_CTYPE_XML), setup_xml); } /*********************************************************************************************\ @@ -338,22 +338,22 @@ const char HUE_DESCRIPTION_XML[] PROGMEM = "1" "0" "" -// "http://{x1}/" - "http://{x1}:80/" +// "http://{x1/" + "http://{x1:80/" "" "urn:schemas-upnp-org:device:Basic:1" - "Amazon-Echo-HA-Bridge ({x1})" -// "Philips hue ({x1})" + "Amazon-Echo-HA-Bridge ({x1)" +// "Philips hue ({x1)" "Royal Philips Electronics" "Philips hue Personal Wireless Lighting" "Philips hue bridge 2012" "929000226503" - "{x3}" - "uuid:{x2}" + "{x3" + "uuid:{x2" "" "\r\n" "\r\n"; -const char HUE_LIGHT_STATUS_JSON[] PROGMEM = +const char HueLightStatus_JSON[] PROGMEM = "\"on\":{state}," "\"bri\":{b}," "\"hue\":{h}," @@ -366,31 +366,31 @@ const char HUE_LIGHT_STATUS_JSON[] PROGMEM = "\"reachable\":true"; const char HUE_LIGHTS_STATUS_JSON[] PROGMEM = "\"type\":\"Extended color light\"," - "\"name\":\"{j1}\"," + "\"name\":\"{j1\"," "\"modelid\":\"LCT007\"," - "\"uniqueid\":\"{j2}\"," + "\"uniqueid\":\"{j2\"," "\"swversion\":\"5.50.1.19085\"" "}"; const char HUE_GROUP0_STATUS_JSON[] PROGMEM = "{\"name\":\"Group 0\"," - "\"lights\":[{l1}]," + "\"lights\":[{l1]," "\"type\":\"LightGroup\"," "\"action\":{"; // "\"scene\":\"none\","; -const char HUE_CONFIG_RESPONSE_JSON[] PROGMEM = +const char HueConfigResponse_JSON[] PROGMEM = "{\"name\":\"Philips hue\"," - "\"mac\":\"{mac}\"," + "\"mac\":\"{ma\"," "\"dhcp\":true," - "\"ipaddress\":\"{ip}\"," - "\"netmask\":\"{mask}\"," - "\"gateway\":\"{gw}\"," + "\"ipaddress\":\"{ip\"," + "\"netmask\":\"{ms\"," + "\"gateway\":\"{gw\"," "\"proxyaddress\":\"none\"," "\"proxyport\":0," - "\"bridgeid\":\"{bid}\"," - "\"UTC\":\"{dt}\"," - "\"whitelist\":{\"{id}\":{" - "\"last use date\":\"{dt}\"," - "\"create date\":\"{dt}\"," + "\"bridgeid\":\"{br\"," + "\"UTC\":\"{dt\"," + "\"whitelist\":{\"{id\":{" + "\"last use date\":\"{dt\"," + "\"create date\":\"{dt\"," "\"name\":\"Remote\"}}," "\"swversion\":\"01039019\"," "\"apiversion\":\"1.17.0\"," @@ -399,20 +399,20 @@ const char HUE_CONFIG_RESPONSE_JSON[] PROGMEM = "\"portalservices\":false" "}"; const char HUE_LIGHT_RESPONSE_JSON[] PROGMEM = - "{\"success\":{\"/lights/{id}/state/{cmd}\":{res}}}"; + "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; const char HUE_ERROR_JSON[] PROGMEM = "[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]"; /********************************************************************************************/ -String hue_deviceId(uint8_t id) +String GetHueDeviceId(uint8_t id) { String deviceid = WiFi.macAddress() + F(":00:11-") + String(id); deviceid.toLowerCase(); return deviceid; // 5c:cf:7f:13:9f:3d:00:11-1 } -String hue_userId() +String GetHueUserId() { char userid[7]; @@ -420,50 +420,50 @@ String hue_userId() return String(userid); } -void handleUPnPsetupHue() +void HandleUpnpSetupHue() { - addLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_HUE_BRIDGE_SETUP)); + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_HUE_BRIDGE_SETUP)); String description_xml = FPSTR(HUE_DESCRIPTION_XML); - description_xml.replace("{x1}", WiFi.localIP().toString()); - description_xml.replace("{x2}", hue_UUID()); - description_xml.replace("{x3}", hue_serial()); - webServer->send(200, FPSTR(HDR_CTYPE_XML), description_xml); + description_xml.replace("{x1", WiFi.localIP().toString()); + description_xml.replace("{x2", HueUuid()); + description_xml.replace("{x3", HueSerialnumber()); + WebServer->send(200, FPSTR(HDR_CTYPE_XML), description_xml); } -void hue_todo(String *path) +void HueNotImplemented(String *path) { snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_HTTP D_HUE_API_NOT_IMPLEMENTED " (%s)"), path->c_str()); - addLog(LOG_LEVEL_DEBUG_MORE); + AddLog(LOG_LEVEL_DEBUG_MORE); - webServer->send(200, FPSTR(HDR_CTYPE_JSON), "{}"); + WebServer->send(200, FPSTR(HDR_CTYPE_JSON), "{}"); } -void hue_config_response(String *response) +void HueConfigResponse(String *response) { - *response += FPSTR(HUE_CONFIG_RESPONSE_JSON); - response->replace("{mac}", WiFi.macAddress()); - response->replace("{ip}", WiFi.localIP().toString()); - response->replace("{mask}", WiFi.subnetMask().toString()); - response->replace("{gw}", WiFi.gatewayIP().toString()); - response->replace("{bid}", hue_bridgeid()); - response->replace("{dt}", getUTCDateTime()); - response->replace("{id}", hue_userId()); + *response += FPSTR(HueConfigResponse_JSON); + response->replace("{ma", WiFi.macAddress()); + response->replace("{ip", WiFi.localIP().toString()); + response->replace("{ms", WiFi.subnetMask().toString()); + response->replace("{gw", WiFi.gatewayIP().toString()); + response->replace("{br", HueBridgeId()); + response->replace("{dt", GetUtcDateAndTime()); + response->replace("{id", GetHueUserId()); } -void hue_config(String *path) +void HueConfig(String *path) { String response = ""; - hue_config_response(&response); - webServer->send(200, FPSTR(HDR_CTYPE_JSON), response); + HueConfigResponse(&response); + WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); } -void hue_light_status(byte device, String *response) +void HueLightStatus(byte device, String *response) { - *response += FPSTR(HUE_LIGHT_STATUS_JSON); - response->replace("{state}", (power & (0x01 << (device-1))) ? "true" : "false"); + *response += FPSTR(HueLightStatus_JSON); + response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false"); - if (sfl_flg) { - sl_replaceHSB(response); + if (light_type) { + LightReplaceHsb(response); } else { response->replace("{h}", "0"); response->replace("{s}", "0"); @@ -471,39 +471,40 @@ void hue_light_status(byte device, String *response) } } -void hue_global_cfg(String *path) +void HueGlobalConfig(String *path) { String response; + uint8_t maxhue = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present; - path->remove(0,1); // cut leading / to get + path->remove(0,1); // cut leading / to get response = F("{\"lights\":{\""); - for (uint8_t i = 1; i <= Maxdevice; i++) { + for (uint8_t i = 1; i <= maxhue; i++) { response += i; response += F("\":{\"state\":{"); - hue_light_status(i, &response); + HueLightStatus(i, &response); response += "},"; response += FPSTR(HUE_LIGHTS_STATUS_JSON); - response.replace("{j1}", sysCfg.friendlyname[i-1]); - response.replace("{j2}", hue_deviceId(i)); - if (i < Maxdevice) { + response.replace("{j1", Settings.friendlyname[i-1]); + response.replace("{j2", GetHueDeviceId(i)); + if (i < maxhue) { response += ",\""; } } response += F("},\"groups\":{},\"schedules\":{},\"config\":"); - hue_config_response(&response); + HueConfigResponse(&response); response += "}"; - webServer->send(200, FPSTR(HDR_CTYPE_JSON), response); + WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); } -void hue_auth(String *path) +void HueAuthentication(String *path) { char response[38]; - snprintf_P(response, sizeof(response), PSTR("[{\"success\":{\"username\":\"%s\"}}]"), hue_userId().c_str()); - webServer->send(200, FPSTR(HDR_CTYPE_JSON), response); + snprintf_P(response, sizeof(response), PSTR("[{\"success\":{\"username\":\"%s\"}}]"), GetHueUserId().c_str()); + WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); } -void hue_lights(String *path) +void HueLights(String *path) { /* * http://sonoff/api/username/lights/1/state?1={"on":true,"hue":56100,"sat":254,"bri":254,"alert":"none","transitiontime":40} @@ -520,60 +521,61 @@ void hue_lights(String *path) bool on = false; bool change = false; char id[4]; + uint8_t maxhue = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present; - path->remove(0,path->indexOf("/lights")); // Remove until /lights - if (path->endsWith("/lights")) { // Got /lights + path->remove(0,path->indexOf("/lights")); // Remove until /lights + if (path->endsWith("/lights")) { // Got /lights response = "{\""; - for (uint8_t i = 1; i <= Maxdevice; i++) { + for (uint8_t i = 1; i <= maxhue; i++) { response += i; response += F("\":{\"state\":{"); - hue_light_status(i, &response); + HueLightStatus(i, &response); response += "},"; response += FPSTR(HUE_LIGHTS_STATUS_JSON); - response.replace("{j1}", sysCfg.friendlyname[i-1]); - response.replace("{j2}", hue_deviceId(i)); - if (i < Maxdevice) { + response.replace("{j1", Settings.friendlyname[i-1]); + response.replace("{j2", GetHueDeviceId(i)); + if (i < maxhue) { response += ",\""; } } response += "}"; - webServer->send(200, FPSTR(HDR_CTYPE_JSON), response); + WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); } - else if (path->endsWith("/state")) { // Got ID/state - path->remove(0,8); // Remove /lights/ - path->remove(path->indexOf("/state")); // Remove /state + else if (path->endsWith("/state")) { // Got ID/state + path->remove(0,8); // Remove /lights/ + path->remove(path->indexOf("/state")); // Remove /state device = atoi(path->c_str()); - if ((device < 1) || (device > Maxdevice)) { + if ((device < 1) || (device > maxhue)) { device = 1; } - if (1 == webServer->args()) { + if (1 == WebServer->args()) { response = "["; StaticJsonBuffer<400> jsonBuffer; - JsonObject &hue_json = jsonBuffer.parseObject(webServer->arg(0)); + JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg(0)); if (hue_json.containsKey("on")) { response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id}", String(device)); - response.replace("{cmd}", "on"); + response.replace("{id", String(device)); + response.replace("{cm", "on"); on = hue_json["on"]; switch(on) { - case false : do_cmnd_power(device, 0); - response.replace("{res}", "false"); + case false : ExecuteCommandPower(device, 0); + response.replace("{re", "false"); break; - case true : do_cmnd_power(device, 1); - response.replace("{res}", "true"); + case true : ExecuteCommandPower(device, 1); + response.replace("{re", "true"); break; - default : response.replace("{res}", (power & (0x01 << (device-1))) ? "true" : "false"); + default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false"); break; } resp = true; } - if (sfl_flg) { - sl_getHSB(&hue,&sat,&bri); + if (light_type) { + LightGetHsb(&hue,&sat,&bri); } if (hue_json.containsKey("bri")) { @@ -583,9 +585,9 @@ void hue_lights(String *path) response += ","; } response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id}", String(device)); - response.replace("{cmd}", "bri"); - response.replace("{res}", String(tmp)); + response.replace("{id", String(device)); + response.replace("{cm", "bri"); + response.replace("{re", String(tmp)); resp = true; change = true; } @@ -596,9 +598,9 @@ void hue_lights(String *path) response += ","; } response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id}", String(device)); - response.replace("{cmd}", "hue"); - response.replace("{res}", String(tmp)); + response.replace("{id", String(device)); + response.replace("{cm", "hue"); + response.replace("{re", String(tmp)); resp = true; change = true; } @@ -609,25 +611,25 @@ void hue_lights(String *path) response += ","; } response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id}", String(device)); - response.replace("{cmd}", "sat"); - response.replace("{res}", String(tmp)); + response.replace("{id", String(device)); + response.replace("{cm", "sat"); + response.replace("{re", String(tmp)); change = true; } - if (hue_json.containsKey("ct")) { // Color temperature 153 (Cold) to 500 (Warm) + if (hue_json.containsKey("ct")) { // Color temperature 153 (Cold) to 500 (Warm) ct = hue_json["ct"]; if (resp) { response += ","; } response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id}", String(device)); - response.replace("{cmd}", "ct"); - response.replace("{res}", String(ct)); + response.replace("{id", String(device)); + response.replace("{cm", "ct"); + response.replace("{re", String(ct)); change = true; } if (change) { - if (sfl_flg) { - sl_setHSB(hue, sat, bri, ct); + if (light_type) { + LightSetHsb(hue, sat, bri, ct); } change = false; } @@ -640,49 +642,50 @@ void hue_lights(String *path) response = FPSTR(HUE_ERROR_JSON); } - webServer->send(200, FPSTR(HDR_CTYPE_JSON), response); + WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); } - else if(path->indexOf("/lights/") >= 0) { // Got /lights/ID - path->remove(0,8); // Remove /lights/ + else if(path->indexOf("/lights/") >= 0) { // Got /lights/ID + path->remove(0,8); // Remove /lights/ device = atoi(path->c_str()); - if ((device < 1) || (device > Maxdevice)) { + if ((device < 1) || (device > maxhue)) { device = 1; } response += F("{\"state\":{"); - hue_light_status(device, &response); + HueLightStatus(device, &response); response += "},"; response += FPSTR(HUE_LIGHTS_STATUS_JSON); - response.replace("{j1}", sysCfg.friendlyname[device-1]); - response.replace("{j2}", hue_deviceId(device)); - webServer->send(200, FPSTR(HDR_CTYPE_JSON), response); + response.replace("{j1", Settings.friendlyname[device-1]); + response.replace("{j2", GetHueDeviceId(device)); + WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); } else { - webServer->send(406, FPSTR(HDR_CTYPE_JSON), "{}"); + WebServer->send(406, FPSTR(HDR_CTYPE_JSON), "{}"); } } -void hue_groups(String *path) +void HueGroups(String *path) { /* * http://sonoff/api/username/groups?1={"name":"Woonkamer","lights":[],"type":"Room","class":"Living room"}) */ String response = "{}"; + uint8_t maxhue = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present; if (path->endsWith("/0")) { response = FPSTR(HUE_GROUP0_STATUS_JSON); String lights = F("\"1\""); - for (uint8_t i = 2; i <= Maxdevice; i++) { + for (uint8_t i = 2; i <= maxhue; i++) { lights += ",\"" + String(i) + "\""; } - response.replace("{l1}", lights); - hue_light_status(1, &response); + response.replace("{l1", lights); + HueLightStatus(1, &response); response += F("}}"); } - webServer->send(200, FPSTR(HDR_CTYPE_JSON), response); + WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); } -void handle_hue_api(String *path) +void HandleHueApi(String *path) { /* HUE API uses /api// syntax. The userid is created by the echo device and * on original HUE the pressed button allows for creation of this user. We simply ignore the @@ -696,24 +699,24 @@ void handle_hue_api(String *path) path->remove(0, 4); // remove /api uint16_t apilen = path->length(); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_HTTP D_HUE_API " (%s)"), path->c_str()); - addLog(LOG_LEVEL_DEBUG_MORE); - for (args = 0; args < webServer->args(); args++) { - String json = webServer->arg(args); + AddLog(LOG_LEVEL_DEBUG_MORE); // HTP: Hue API (//lights/1/state) + for (args = 0; args < WebServer->args(); args++) { + String json = WebServer->arg(args); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_HTTP D_HUE_POST_ARGS " (%s)"), json.c_str()); - addLog(LOG_LEVEL_DEBUG_MORE); + AddLog(LOG_LEVEL_DEBUG_MORE); // HTP: Hue POST args ({"on":false}) } - if (path->endsWith("/invalid/")) {} // Just ignore - else if (!apilen) hue_auth(path); // New HUE App setup - else if (path->endsWith("/")) hue_auth(path); // New HUE App setup - else if (path->endsWith("/config")) hue_config(path); - else if (path->indexOf("/lights") >= 0) hue_lights(path); - else if (path->indexOf("/groups") >= 0) hue_groups(path); - else if (path->endsWith("/schedules")) hue_todo(path); - else if (path->endsWith("/sensors")) hue_todo(path); - else if (path->endsWith("/scenes")) hue_todo(path); - else if (path->endsWith("/rules")) hue_todo(path); - else hue_global_cfg(path); + if (path->endsWith("/invalid/")) {} // Just ignore + else if (!apilen) HueAuthentication(path); // New HUE App setup + else if (path->endsWith("/")) HueAuthentication(path); // New HUE App setup + else if (path->endsWith("/config")) HueConfig(path); + else if (path->indexOf("/lights") >= 0) HueLights(path); + else if (path->indexOf("/groups") >= 0) HueGroups(path); + else if (path->endsWith("/schedules")) HueNotImplemented(path); + else if (path->endsWith("/sensors")) HueNotImplemented(path); + else if (path->endsWith("/scenes")) HueNotImplemented(path); + else if (path->endsWith("/rules")) HueNotImplemented(path); + else HueGlobalConfig(path); } #endif // USE_WEBSERVER #endif // USE_EMULATION diff --git a/sonoff/xdrv_ws2812.ino b/sonoff/xdrv_ws2812.ino index ea2d1bba8..6b38ba3c3 100644 --- a/sonoff/xdrv_ws2812.ino +++ b/sonoff/xdrv_ws2812.ino @@ -38,65 +38,54 @@ #endif // USE_WS2812_CTYPE #endif // USE_WS2812_DMA -struct wsColor { +struct WsColor { uint8_t red, green, blue; }; struct ColorScheme { - wsColor* colors; + WsColor* colors; uint8_t count; }; -wsColor incandescent[2] = { 255, 140, 20, 0, 0, 0 }; -wsColor rgb[3] = { 255, 0, 0, 0, 255, 0, 0, 0, 255 }; -wsColor christmas[2] = { 255, 0, 0, 0, 255, 0 }; -wsColor hanukkah[2] = { 0, 0, 255, 255, 255, 255 }; -wsColor kwanzaa[3] = { 255, 0, 0, 0, 0, 0, 0, 255, 0 }; -wsColor rainbow[7] = { 255, 0, 0, 255, 128, 0, 255, 255, 0, 0, 255, 0, 0, 0, 255, 128, 0, 255, 255, 0, 255 }; -wsColor fire[3] = { 255, 0, 0, 255, 102, 0, 255, 192, 0 }; -ColorScheme schemes[7] = { - incandescent, 2, - rgb, 3, - christmas, 2, - hanukkah, 2, +WsColor kIncandescent[2] = { 255, 140, 20, 0, 0, 0 }; +WsColor kRgb[3] = { 255, 0, 0, 0, 255, 0, 0, 0, 255 }; +WsColor kChristmas[2] = { 255, 0, 0, 0, 255, 0 }; +WsColor kHanukkah[2] = { 0, 0, 255, 255, 255, 255 }; +WsColor kwanzaa[3] = { 255, 0, 0, 0, 0, 0, 0, 255, 0 }; +WsColor kRainbow[7] = { 255, 0, 0, 255, 128, 0, 255, 255, 0, 0, 255, 0, 0, 0, 255, 128, 0, 255, 255, 0, 255 }; +WsColor kFire[3] = { 255, 0, 0, 255, 102, 0, 255, 192, 0 }; +ColorScheme kSchemes[7] = { + kIncandescent, 2, + kRgb, 3, + kChristmas, 2, + kHanukkah, 2, kwanzaa, 3, - rainbow, 7, - fire, 3 }; + kRainbow, 7, + kFire, 3 }; -uint8_t widthValues[5] = { +uint8_t kWidth[5] = { 1, // Small 2, // Medium 4, // Large 8, // Largest 255 }; // All -uint8_t repeatValues[5] = { +uint8_t kRepeat[5] = { 8, // Small 6, // Medium 4, // Large 2, // Largest 1 }; // All -uint8_t speedValues[9] = { - 0, // None - 1 * (STATES / 10), // Fastest - 3 * (STATES / 10), - 5 * (STATES / 10), // Fast - 7 * (STATES / 10), - 9 * (STATES / 10), - 11 * (STATES / 10), // Slow - 13 * (STATES / 10), - 15 * (STATES / 10) }; // Slowest - -uint8_t ws2812_showNext = 1; +uint8_t ws_show_next = 1; /********************************************************************************************/ -void ws2812_stripShow() +void Ws2812StripShow() { RgbColor c; - if (sysCfg.led_table) { - for (uint16_t i = 0; i < sysCfg.led_pixels; i++) { + if (Settings.light_correction) { + for (uint16_t i = 0; i < Settings.light_pixels; i++) { c = strip->GetPixelColor(i); strip->SetPixelColor(i, RgbColor(ledTable[c.R], ledTable[c.G], ledTable[c.B])); } @@ -113,44 +102,56 @@ int mod(int a, int b) return ret; } -void ws2812_clock() +#define cmin(a,b) ((a)<(b)?(a):(b)) + +void Ws2812UpdatePixelColor(int position, struct RgbColor hand_color, uint8_t hand) { - RgbColor c; + RgbColor color; - strip->ClearTo(0); // Reset strip - float newDim = 100 / (float)sysCfg.led_dimmer[0]; - float f1 = 255 / newDim; - uint8_t i1 = (uint8_t)f1; - float f2 = 127 / newDim; - uint8_t i2 = (uint8_t)f2; - float f3 = 63 / newDim; - uint8_t i3 = (uint8_t)f3; + uint16_t mod_position = mod(position, (int)Settings.light_pixels); - int j = sysCfg.led_pixels; - int clksize = 600 / j; - int i = (rtcTime.Second * 10) / clksize; - - c = strip->GetPixelColor(mod(i, j)); c.B = i1; strip->SetPixelColor(mod(i, j), c); - i = (rtcTime.Minute * 10) / clksize; - c = strip->GetPixelColor(mod(i -1, j)); c.G = i3; strip->SetPixelColor(mod(i -1, j), c); - c = strip->GetPixelColor(mod(i, j)); c.G = i1; strip->SetPixelColor(mod(i, j), c); - c = strip->GetPixelColor(mod(i +1, j)); c.G = i3; strip->SetPixelColor(mod(i +1, j), c); - i = (rtcTime.Hour % 12) * (50 / clksize); - c = strip->GetPixelColor(mod(i -2, j)); c.R = i3; strip->SetPixelColor(mod(i -2, j), c); - c = strip->GetPixelColor(mod(i -1, j)); c.R = i2; strip->SetPixelColor(mod(i -1, j), c); - c = strip->GetPixelColor(mod(i, j)); c.R = i1; strip->SetPixelColor(mod(i, j), c); - c = strip->GetPixelColor(mod(i +1, j)); c.R = i2; strip->SetPixelColor(mod(i +1, j), c); - c = strip->GetPixelColor(mod(i +2, j)); c.R = i3; strip->SetPixelColor(mod(i +2, j), c); - ws2812_stripShow(); + color = strip->GetPixelColor(mod_position); + float dimmer = 100 / (float)Settings.light_dimmer; + uint8_t offset = 1 << hand; + color.R = cmin(color.R + ((hand_color.R / dimmer) / offset), 255); + color.G = cmin(color.G + ((hand_color.G / dimmer) / offset), 255); + color.B = cmin(color.B + ((hand_color.B / dimmer) / offset), 255); + strip->SetPixelColor(mod_position, color); } -void ws2812_gradientColor(uint8_t schemenr, struct wsColor* mColor, uint16_t range, uint16_t gradRange, uint16_t i) +void Ws2812UpdateHand(int position, uint8_t index) +{ + if (Settings.flag.ws_clock_reverse) { + position = Settings.light_pixels -position; + } + RgbColor hand_color = RgbColor(Settings.ws_color[index][WS_RED], Settings.ws_color[index][WS_GREEN], Settings.ws_color[index][WS_BLUE]); + + Ws2812UpdatePixelColor(position, hand_color, 0); + for (uint8_t h = 1; h <= ((Settings.ws_width[index] -1) / 2); h++) { + Ws2812UpdatePixelColor(position -h, hand_color, h); + Ws2812UpdatePixelColor(position +h, hand_color, h); + } +} + +void Ws2812Clock() +{ + strip->ClearTo(0); // Reset strip + int clksize = 600 / (int)Settings.light_pixels; + Ws2812UpdateHand((RtcTime.second * 10) / clksize, WS_SECOND); + Ws2812UpdateHand((RtcTime.minute * 10) / clksize, WS_MINUTE); +// Ws2812UpdateHand((RtcTime.hour % 12) * (50 / clksize), WS_HOUR); + Ws2812UpdateHand(((RtcTime.hour % 12) * (50 / clksize)) + ((RtcTime.minute * 10) / (12 * clksize)), WS_HOUR); + + Ws2812StripShow(); +} + +void Ws2812GradientColor(uint8_t schemenr, struct WsColor* mColor, uint16_t range, uint16_t gradRange, uint16_t i) { /* * Compute the color of a pixel at position i using a gradient of the color scheme. * This function is used internally by the gradient function. */ - ColorScheme scheme = schemes[schemenr]; + ColorScheme scheme = kSchemes[schemenr]; uint16_t curRange = i / range; uint16_t rangeIndex = i % range; uint16_t colorIndex = rangeIndex / gradRange; @@ -160,16 +161,16 @@ void ws2812_gradientColor(uint8_t schemenr, struct wsColor* mColor, uint16_t ran start = (scheme.count -1) - start; end = (scheme.count -1) - end; } - float newDim = 100 / (float)sysCfg.led_dimmer[0]; - float fmyRed = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].red, scheme.colors[end].red) / newDim; - float fmyGrn = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].green, scheme.colors[end].green) / newDim; - float fmyBlu = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].blue, scheme.colors[end].blue) / newDim; + float dimmer = 100 / (float)Settings.light_dimmer; + float fmyRed = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].red, scheme.colors[end].red) / dimmer; + float fmyGrn = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].green, scheme.colors[end].green) / dimmer; + float fmyBlu = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].blue, scheme.colors[end].blue) / dimmer; mColor->red = (uint8_t)fmyRed; mColor->green = (uint8_t)fmyGrn; mColor->blue = (uint8_t)fmyBlu; } -void ws2812_gradient(uint8_t schemenr) +void Ws2812Gradient(uint8_t schemenr) { /* * This routine courtesy Tony DiCola (Adafruit) @@ -178,28 +179,29 @@ void ws2812_gradient(uint8_t schemenr) */ RgbColor c; - ColorScheme scheme = schemes[schemenr]; + ColorScheme scheme = kSchemes[schemenr]; if (scheme.count < 2) { return; } - uint8_t repeat = repeatValues[sysCfg.led_width]; // number of scheme.count per ledcount - uint16_t range = (uint16_t)ceil((float)sysCfg.led_pixels / (float)repeat); + uint8_t repeat = kRepeat[Settings.light_width]; // number of scheme.count per ledcount + uint16_t range = (uint16_t)ceil((float)Settings.light_pixels / (float)repeat); uint16_t gradRange = (uint16_t)ceil((float)range / (float)(scheme.count - 1)); - uint16_t offset = speedValues[sysCfg.led_speed] > 0 ? stripTimerCntr / speedValues[sysCfg.led_speed] : 0; + uint16_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10); + uint16_t offset = speed > 0 ? strip_timer_counter / speed : 0; - wsColor oldColor, currentColor; - ws2812_gradientColor(schemenr, &oldColor, range, gradRange, offset); + WsColor oldColor, currentColor; + Ws2812GradientColor(schemenr, &oldColor, range, gradRange, offset); currentColor = oldColor; - for (uint16_t i = 0; i < sysCfg.led_pixels; i++) { - if (repeatValues[sysCfg.led_width] > 1) { - ws2812_gradientColor(schemenr, ¤tColor, range, gradRange, i +offset); + for (uint16_t i = 0; i < Settings.light_pixels; i++) { + if (kRepeat[Settings.light_width] > 1) { + Ws2812GradientColor(schemenr, ¤tColor, range, gradRange, i +offset); } - if (sysCfg.led_speed > 0) { + if (Settings.light_speed > 0) { // Blend old and current color based on time for smooth movement. - c.R = map(stripTimerCntr % speedValues[sysCfg.led_speed], 0, speedValues[sysCfg.led_speed], oldColor.red, currentColor.red); - c.G = map(stripTimerCntr % speedValues[sysCfg.led_speed], 0, speedValues[sysCfg.led_speed], oldColor.green, currentColor.green); - c.B = map(stripTimerCntr % speedValues[sysCfg.led_speed], 0, speedValues[sysCfg.led_speed], oldColor.blue, currentColor.blue); + c.R = map(strip_timer_counter % speed, 0, speed, oldColor.red, currentColor.red); + c.G = map(strip_timer_counter % speed, 0, speed, oldColor.green, currentColor.green); + c.B = map(strip_timer_counter % speed, 0, speed, oldColor.blue, currentColor.blue); } else { // No animation, just use the current color. @@ -210,10 +212,10 @@ void ws2812_gradient(uint8_t schemenr) strip->SetPixelColor(i, c); oldColor = currentColor; } - ws2812_stripShow(); + Ws2812StripShow(); } -void ws2812_bars(uint8_t schemenr) +void Ws2812Bars(uint8_t schemenr) { /* * This routine courtesy Tony DiCola (Adafruit) @@ -223,44 +225,45 @@ void ws2812_bars(uint8_t schemenr) RgbColor c; uint16_t i; - ColorScheme scheme = schemes[schemenr]; + ColorScheme scheme = kSchemes[schemenr]; - uint16_t maxSize = sysCfg.led_pixels / scheme.count; - if (widthValues[sysCfg.led_width] > maxSize) { + uint16_t maxSize = Settings.light_pixels / scheme.count; + if (kWidth[Settings.light_width] > maxSize) { maxSize = 0; } - uint8_t offset = speedValues[sysCfg.led_speed] > 0 ? stripTimerCntr / speedValues[sysCfg.led_speed] : 0; + uint16_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10); + uint8_t offset = speed > 0 ? strip_timer_counter / speed : 0; - wsColor mcolor[scheme.count]; + WsColor mcolor[scheme.count]; memcpy(mcolor, scheme.colors, sizeof(mcolor)); - float newDim = 100 / (float)sysCfg.led_dimmer[0]; + float dimmer = 100 / (float)Settings.light_dimmer; for (i = 0; i < scheme.count; i++) { - float fmyRed = (float)mcolor[i].red / newDim; - float fmyGrn = (float)mcolor[i].green / newDim; - float fmyBlu = (float)mcolor[i].blue / newDim; + float fmyRed = (float)mcolor[i].red / dimmer; + float fmyGrn = (float)mcolor[i].green / dimmer; + float fmyBlu = (float)mcolor[i].blue / dimmer; mcolor[i].red = (uint8_t)fmyRed; mcolor[i].green = (uint8_t)fmyGrn; mcolor[i].blue = (uint8_t)fmyBlu; } uint8_t colorIndex = offset % scheme.count; - for (i = 0; i < sysCfg.led_pixels; i++) { + for (i = 0; i < Settings.light_pixels; i++) { if (maxSize) { - colorIndex = ((i + offset) % (scheme.count * widthValues[sysCfg.led_width])) / widthValues[sysCfg.led_width]; + colorIndex = ((i + offset) % (scheme.count * kWidth[Settings.light_width])) / kWidth[Settings.light_width]; } c.R = mcolor[colorIndex].red; c.G = mcolor[colorIndex].green; c.B = mcolor[colorIndex].blue; strip->SetPixelColor(i, c); } - ws2812_stripShow(); + Ws2812StripShow(); } /*********************************************************************************************\ * Public \*********************************************************************************************/ -void ws2812_init() +void Ws2812Init() { #ifdef USE_WS2812_DMA #if (USE_WS2812_CTYPE == 1) @@ -276,17 +279,17 @@ void ws2812_init() #endif // USE_WS2812_CTYPE #endif // USE_WS2812_DMA strip->Begin(); - ws2812_clear(); + Ws2812Clear(); } -void ws2812_clear() +void Ws2812Clear() { strip->ClearTo(0); strip->Show(); - ws2812_showNext = 1; + ws_show_next = 1; } -void ws2812_setColor(uint16_t led, uint8_t red, uint8_t green, uint8_t blue) +void Ws2812SetColor(uint16_t led, uint8_t red, uint8_t green, uint8_t blue) { RgbColor lcolor; lcolor.R = red; @@ -296,15 +299,15 @@ void ws2812_setColor(uint16_t led, uint8_t red, uint8_t green, uint8_t blue) strip->SetPixelColor(led -1, lcolor); // Led 1 is strip Led 0 -> substract offset 1 } else { // strip->ClearTo(lcolor); // Set WS2812_MAX_LEDS pixels - for (uint16_t i = 0; i < sysCfg.led_pixels; i++) { + for (uint16_t i = 0; i < Settings.light_pixels; i++) { strip->SetPixelColor(i, lcolor); } } strip->Show(); - ws2812_showNext = 1; + ws_show_next = 1; } -char* ws2812_getColor(uint16_t led, char* scolor) +char* Ws2812GetColor(uint16_t led, char* scolor) { uint8_t sl_ledcolor[3]; @@ -314,27 +317,31 @@ char* ws2812_getColor(uint16_t led, char* scolor) sl_ledcolor[2] = lcolor.B; scolor[0] = '\0'; for (byte i = 0; i < 3; i++) { - snprintf_P(scolor, 11, PSTR("%s%02X"), scolor, sl_ledcolor[i]); + if (Settings.flag.decimal_text) { + snprintf_P(scolor, 25, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", sl_ledcolor[i]); + } else { + snprintf_P(scolor, 25, PSTR("%s%02X"), scolor, sl_ledcolor[i]); + } } return scolor; } -void ws2812_showScheme(uint8_t scheme) +void Ws2812ShowScheme(uint8_t scheme) { switch (scheme) { case 0: // Clock - if (((STATES/10)*2 == state) || (ws2812_showNext)) { - ws2812_clock(); - ws2812_showNext = 0; + if (((STATES/10)*2 == state) || (ws_show_next)) { + Ws2812Clock(); + ws_show_next = 0; } break; default: - if (1 == sysCfg.led_fade) { - ws2812_gradient(scheme -1); + if (1 == Settings.light_fade) { + Ws2812Gradient(scheme -1); } else { - ws2812_bars(scheme -1); + Ws2812Bars(scheme -1); } - ws2812_showNext = 1; + ws_show_next = 1; break; } } diff --git a/sonoff/xsns_bh1750.ino b/sonoff/xsns_bh1750.ino index e0a96ca61..96b93c21c 100644 --- a/sonoff/xsns_bh1750.ino +++ b/sonoff/xsns_bh1750.ino @@ -28,48 +28,48 @@ #define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 // Start measurement at 1lx resolution. Measurement time is approx 120ms. -uint8_t bh1750addr; -uint8_t bh1750type = 0; -char bh1750stype[7]; +uint8_t bh1750_address; +uint8_t bh1750_type = 0; +char bh1750_types[7]; -uint16_t bh1750_readLux(void) +uint16_t Bh1750ReadLux() { - Wire.requestFrom(bh1750addr, (uint8_t)2); + Wire.requestFrom(bh1750_address, (uint8_t)2); byte msb = Wire.read(); byte lsb = Wire.read(); uint16_t value = ((msb << 8) | lsb) / 1.2; return value; } -boolean bh1750_detect() +boolean Bh1750Detect() { - if (bh1750type) { + if (bh1750_type) { return true; } uint8_t status; boolean success = false; - bh1750addr = BH1750_ADDR1; - Wire.beginTransmission(bh1750addr); + bh1750_address = BH1750_ADDR1; + Wire.beginTransmission(bh1750_address); Wire.write(BH1750_CONTINUOUS_HIGH_RES_MODE); status = Wire.endTransmission(); if (status) { - bh1750addr = BH1750_ADDR2; - Wire.beginTransmission(bh1750addr); + bh1750_address = BH1750_ADDR2; + Wire.beginTransmission(bh1750_address); Wire.write(BH1750_CONTINUOUS_HIGH_RES_MODE); status = Wire.endTransmission(); } if (!status) { success = true; - bh1750type = 1; - strcpy_P(bh1750stype, PSTR("BH1750")); + bh1750_type = 1; + strcpy_P(bh1750_types, PSTR("BH1750")); } if (success) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "%s " D_FOUND_AT " 0x%x"), bh1750stype, bh1750addr); - addLog(LOG_LEVEL_DEBUG); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "%s " D_FOUND_AT " 0x%x"), bh1750_types, bh1750_address); + AddLog(LOG_LEVEL_DEBUG); } else { - bh1750type = 0; + bh1750_type = 0; } return success; } @@ -78,30 +78,30 @@ boolean bh1750_detect() * Presentation \*********************************************************************************************/ -void bh1750_mqttPresent(uint8_t* djson) +void MqttShowBh1750(uint8_t* djson) { - if (!bh1750type) { + if (!bh1750_type) { return; } - uint16_t l = bh1750_readLux(); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_ILLUMINANCE "\":%d}"), mqtt_data, bh1750stype, l); + uint16_t l = Bh1750ReadLux(); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_ILLUMINANCE "\":%d}"), mqtt_data, bh1750_types, l); *djson = 1; #ifdef USE_DOMOTICZ - domoticz_sensor5(l); + DomoticzSensor(DZ_ILLUMINANCE, l); #endif // USE_DOMOTICZ } #ifdef USE_WEBSERVER const char HTTP_SNS_ILLUMINANCE[] PROGMEM = - "BH1750 " D_ILLUMINANCE "%d lx"; + "BH1750 " D_ILLUMINANCE "%d " D_UNIT_LUX ""; -String bh1750_webPresent() +String WebShowBh1750() { String page = ""; - if (bh1750type) { + if (bh1750_type) { char sensor[80]; - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_ILLUMINANCE, bh1750_readLux()); + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_ILLUMINANCE, Bh1750ReadLux()); page += sensor; } return page; diff --git a/sonoff/xsns_bmp.ino b/sonoff/xsns_bmp.ino index 0d5f2830d..fd7b33f93 100644 --- a/sonoff/xsns_bmp.ino +++ b/sonoff/xsns_bmp.ino @@ -33,14 +33,13 @@ #define BMP_REGISTER_CHIPID 0xD0 -uint8_t bmpaddr; -uint8_t bmptype = 0; -char bmpstype[7]; +double bmp_sealevel = 0.0; +uint8_t bmp_address; +uint8_t bmp_type = 0; +char bmp_types[7]; /*********************************************************************************************\ * BMP085 and BME180 - * - * Programmer : Heiko Krupp with changes from Theo Arends \*********************************************************************************************/ #define BMP180_REG_CONTROL 0xF4 @@ -62,91 +61,91 @@ char bmpstype[7]; #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; +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; -int32_t bmp180_b5 = 0; +int32_t bmp180_b5 = 0; -boolean bmp180_calibration() +boolean Bmp180Calibration() { - cal_ac1 = i2c_read16(bmpaddr, BMP180_AC1); - cal_ac2 = i2c_read16(bmpaddr, BMP180_AC2); - cal_ac3 = i2c_read16(bmpaddr, BMP180_AC3); - cal_ac4 = i2c_read16(bmpaddr, BMP180_AC4); - cal_ac5 = i2c_read16(bmpaddr, BMP180_AC5); - cal_ac6 = i2c_read16(bmpaddr, BMP180_AC6); - cal_b1 = i2c_read16(bmpaddr, BMP180_VB1); - cal_b2 = i2c_read16(bmpaddr, BMP180_VB2); - cal_mc = i2c_read16(bmpaddr, BMP180_MC); - cal_md = i2c_read16(bmpaddr, BMP180_MD); + 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); // 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) { return false; } - if ((cal_ac1 == 0xFFFF)| - (cal_ac2 == 0xFFFF)| - (cal_ac3 == 0xFFFF)| - (cal_ac4 == 0xFFFF)| - (cal_ac5 == 0xFFFF)| - (cal_ac6 == 0xFFFF)| - (cal_b1 == 0xFFFF)| - (cal_b2 == 0xFFFF)| - (cal_mc == 0xFFFF)| + if ((cal_ac1 == 0xFFFF) | + (cal_ac2 == 0xFFFF) | + (cal_ac3 == 0xFFFF) | + (cal_ac4 == 0xFFFF) | + (cal_ac5 == 0xFFFF) | + (cal_ac6 == 0xFFFF) | + (cal_b1 == 0xFFFF) | + (cal_b2 == 0xFFFF) | + (cal_mc == 0xFFFF) | (cal_md == 0xFFFF)) { return false; } - return true; } -double bmp180_readTemperature() +double Bmp180ReadTemperature() { - i2c_write8(bmpaddr, BMP180_REG_CONTROL, BMP180_TEMPERATURE); + I2cWrite8(bmp_address, BMP180_REG_CONTROL, BMP180_TEMPERATURE); delay(5); // 5ms conversion time - int ut = i2c_read16(bmpaddr, BMP180_REG_RESULT); + int ut = I2cRead16(bmp_address, BMP180_REG_RESULT); int32_t x1 = (ut - (int32_t)cal_ac6) * ((int32_t)cal_ac5) >> 15; - int32_t x2 = ((int32_t)cal_mc << 11) / (x1+(int32_t)cal_md); - bmp180_b5=x1+x2; + int32_t x2 = ((int32_t)cal_mc << 11) / (x1 + (int32_t)cal_md); + bmp180_b5 = x1 + x2; - return ((bmp180_b5+8)>>4)/10.0; + return ((bmp180_b5 + 8) >> 4) / 10.0; } -double bmp180_readPressure() +double Bmp180ReadPressure() { int32_t p; uint8_t msb; uint8_t lsb; uint8_t xlsb; - i2c_write8(bmpaddr, BMP180_REG_CONTROL, BMP180_PRESSURE3); // Highest resolution - delay(2 + (4 << BMP180_OSS)); // 26ms conversion time at ultra high resolution - uint32_t up = i2c_read24(bmpaddr, BMP180_REG_RESULT); + I2cWrite8(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); up >>= (8 - BMP180_OSS); int32_t b6 = bmp180_b5 - 4000; - int32_t x1 = ((int32_t)cal_b2 * ( (b6 * b6)>>12 )) >> 11; + int32_t x1 = ((int32_t)cal_b2 * ((b6 * b6) >> 12)) >> 11; int32_t x2 = ((int32_t)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)cal_ac1 * 4 + x3) << BMP180_OSS) + 2) >> 2; x1 = ((int32_t)cal_ac3 * b6) >> 13; x2 = ((int32_t)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 b7 = ((uint32_t)up - b3) * (uint32_t)( 50000UL >> BMP180_OSS); + uint32_t b7 = ((uint32_t)up - b3) * (uint32_t)(50000UL >> BMP180_OSS); if (b7 < 0x80000000) { p = (b7 * 2) / b4; - } else { + } + else { p = (b7 / b4) * 2; } @@ -154,14 +153,8 @@ double bmp180_readPressure() x1 = (x1 * 3038) >> 16; x2 = (-7357 * p) >> 16; - p += ((x1 + x2 + (int32_t)3791)>>4); - return p/100.0; // convert to mbar -} - -double bmp180_calcSealevelPressure(float pAbs, float altitude_meters) -{ - double pressure = pAbs*100.0; - return (double)(pressure / pow(1.0-altitude_meters/44330, 5.255))/100.0; + p += ((x1 + x2 + (int32_t)3791) >> 4); + return p / 100.0; // convert to mbar } /*********************************************************************************************\ @@ -170,32 +163,32 @@ double bmp180_calcSealevelPressure(float pAbs, float altitude_meters) * Programmer : BMP280/BME280 Datasheet and Adafruit with changes by Theo Arends \*********************************************************************************************/ -#define BME280_REGISTER_CONTROLHUMID 0xF2 -#define BME280_REGISTER_CONTROL 0xF4 -#define BME280_REGISTER_PRESSUREDATA 0xF7 -#define BME280_REGISTER_TEMPDATA 0xFA -#define BME280_REGISTER_HUMIDDATA 0xFD +#define BME280_REGISTER_CONTROLHUMID 0xF2 +#define BME280_REGISTER_CONTROL 0xF4 +#define BME280_REGISTER_PRESSUREDATA 0xF7 +#define BME280_REGISTER_TEMPDATA 0xFA +#define BME280_REGISTER_HUMIDDATA 0xFD -#define BME280_REGISTER_DIG_T1 0x88 -#define BME280_REGISTER_DIG_T2 0x8A -#define BME280_REGISTER_DIG_T3 0x8C -#define BME280_REGISTER_DIG_P1 0x8E -#define BME280_REGISTER_DIG_P2 0x90 -#define BME280_REGISTER_DIG_P3 0x92 -#define BME280_REGISTER_DIG_P4 0x94 -#define BME280_REGISTER_DIG_P5 0x96 -#define BME280_REGISTER_DIG_P6 0x98 -#define BME280_REGISTER_DIG_P7 0x9A -#define BME280_REGISTER_DIG_P8 0x9C -#define BME280_REGISTER_DIG_P9 0x9E -#define BME280_REGISTER_DIG_H1 0xA1 -#define BME280_REGISTER_DIG_H2 0xE1 -#define BME280_REGISTER_DIG_H3 0xE3 -#define BME280_REGISTER_DIG_H4 0xE4 -#define BME280_REGISTER_DIG_H5 0xE5 -#define BME280_REGISTER_DIG_H6 0xE7 +#define BME280_REGISTER_DIG_T1 0x88 +#define BME280_REGISTER_DIG_T2 0x8A +#define BME280_REGISTER_DIG_T3 0x8C +#define BME280_REGISTER_DIG_P1 0x8E +#define BME280_REGISTER_DIG_P2 0x90 +#define BME280_REGISTER_DIG_P3 0x92 +#define BME280_REGISTER_DIG_P4 0x94 +#define BME280_REGISTER_DIG_P5 0x96 +#define BME280_REGISTER_DIG_P6 0x98 +#define BME280_REGISTER_DIG_P7 0x9A +#define BME280_REGISTER_DIG_P8 0x9C +#define BME280_REGISTER_DIG_P9 0x9E +#define BME280_REGISTER_DIG_H1 0xA1 +#define BME280_REGISTER_DIG_H2 0xE1 +#define BME280_REGISTER_DIG_H3 0xE3 +#define BME280_REGISTER_DIG_H4 0xE4 +#define BME280_REGISTER_DIG_H5 0xE5 +#define BME280_REGISTER_DIG_H6 0xE7 -struct bme280_calib_data +struct BME280CALIBDATA { uint16_t dig_T1; int16_t dig_T2; @@ -215,212 +208,201 @@ struct bme280_calib_data int16_t dig_H4; int16_t dig_H5; int8_t dig_H6; -} _bme280_calib; +} Bme280CalibrationData; int32_t t_fine; -boolean bmp280_calibrate() +boolean Bmx280Calibrate() { -// if (i2c_read8(bmpaddr, BMP_REGISTER_CHIPID) != BMP280_CHIPID) return false; + // if (I2cRead8(bmp_address, BMP_REGISTER_CHIPID) != BME280_CHIPID) return false; - _bme280_calib.dig_T1 = i2c_read16_LE(bmpaddr, BME280_REGISTER_DIG_T1); - _bme280_calib.dig_T2 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_T2); - _bme280_calib.dig_T3 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_T3); - _bme280_calib.dig_P1 = i2c_read16_LE(bmpaddr, BME280_REGISTER_DIG_P1); - _bme280_calib.dig_P2 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P2); - _bme280_calib.dig_P3 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P3); - _bme280_calib.dig_P4 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P4); - _bme280_calib.dig_P5 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P5); - _bme280_calib.dig_P6 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P6); - _bme280_calib.dig_P7 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P7); - _bme280_calib.dig_P8 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P8); - _bme280_calib.dig_P9 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P9); + 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) { + 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); -// i2c_write8(bmpaddr, BME280_REGISTER_CONTROL, 0x3F); // Temp 1x oversampling, Press 16x oversampling, normal mode (Adafruit) - i2c_write8(bmpaddr, BME280_REGISTER_CONTROL, 0xB7); // 16x oversampling, normal mode (Adafruit) + // Set before CONTROL_meas (DS 5.4.3) + I2cWrite8(bmp_address, BME280_REGISTER_CONTROLHUMID, 0x05); // 16x oversampling (Adafruit) + } + I2cWrite8(bmp_address, BME280_REGISTER_CONTROL, 0xB7); // 16x oversampling, normal mode (Adafruit) return true; } -boolean bme280_calibrate() -{ -// if (i2c_read8(bmpaddr, BMP_REGISTER_CHIPID) != BME280_CHIPID) return false; - - _bme280_calib.dig_T1 = i2c_read16_LE(bmpaddr, BME280_REGISTER_DIG_T1); - _bme280_calib.dig_T2 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_T2); - _bme280_calib.dig_T3 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_T3); - _bme280_calib.dig_P1 = i2c_read16_LE(bmpaddr, BME280_REGISTER_DIG_P1); - _bme280_calib.dig_P2 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P2); - _bme280_calib.dig_P3 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P3); - _bme280_calib.dig_P4 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P4); - _bme280_calib.dig_P5 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P5); - _bme280_calib.dig_P6 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P6); - _bme280_calib.dig_P7 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P7); - _bme280_calib.dig_P8 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P8); - _bme280_calib.dig_P9 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_P9); - _bme280_calib.dig_H1 = i2c_read8(bmpaddr, BME280_REGISTER_DIG_H1); - _bme280_calib.dig_H2 = i2c_readS16_LE(bmpaddr, BME280_REGISTER_DIG_H2); - _bme280_calib.dig_H3 = i2c_read8(bmpaddr, BME280_REGISTER_DIG_H3); - _bme280_calib.dig_H4 = (i2c_read8(bmpaddr, BME280_REGISTER_DIG_H4) << 4) | (i2c_read8(bmpaddr, BME280_REGISTER_DIG_H4 + 1) & 0xF); - _bme280_calib.dig_H5 = (i2c_read8(bmpaddr, BME280_REGISTER_DIG_H5 + 1) << 4) | (i2c_read8(bmpaddr, BME280_REGISTER_DIG_H5) >> 4); - _bme280_calib.dig_H6 = (int8_t)i2c_read8(bmpaddr, BME280_REGISTER_DIG_H6); - - // Set before CONTROL_meas (DS 5.4.3) - i2c_write8(bmpaddr, BME280_REGISTER_CONTROLHUMID, 0x05); // 16x oversampling (Adafruit) - i2c_write8(bmpaddr, BME280_REGISTER_CONTROL, 0xB7); // 16x oversampling, normal mode (Adafruit) - - return true; -} - -double bmp280_readTemperature(void) +double Bme280ReadTemperature(void) { int32_t var1; int32_t var2; - int32_t adc_T = i2c_read24(bmpaddr, BME280_REGISTER_TEMPDATA); + int32_t adc_T = I2cRead24(bmp_address, BME280_REGISTER_TEMPDATA); adc_T >>= 4; - var1 = ((((adc_T>>3) - ((int32_t)_bme280_calib.dig_T1 <<1))) * ((int32_t)_bme280_calib.dig_T2)) >> 11; - var2 = (((((adc_T>>4) - ((int32_t)_bme280_calib.dig_T1)) * ((adc_T>>4) - ((int32_t)_bme280_calib.dig_T1))) >> 12) * - ((int32_t)_bme280_calib.dig_T3)) >> 14; + var1 = ((((adc_T >> 3) - ((int32_t)Bme280CalibrationData.dig_T1 << 1))) * ((int32_t)Bme280CalibrationData.dig_T2)) >> 11; + var2 = (((((adc_T >> 4) - ((int32_t)Bme280CalibrationData.dig_T1)) * ((adc_T >> 4) - ((int32_t)Bme280CalibrationData.dig_T1))) >> 12) * + ((int32_t)Bme280CalibrationData.dig_T3)) >> 14; t_fine = var1 + var2; - double T = (t_fine * 5 + 128) >> 8; + double T = (t_fine * 5 + 128) >> 8; return T / 100.0; } -double bmp280_readPressure(void) +double Bme280ReadPressure(void) { int64_t var1; int64_t var2; int64_t p; -// Must be done first to get the t_fine variable set up -// bmp280_readTemperature(); + // Must be done first to get the t_fine variable set up + // Bme280ReadTemperature(); - int32_t adc_P = i2c_read24(bmpaddr, BME280_REGISTER_PRESSUREDATA); + int32_t adc_P = I2cRead24(bmp_address, BME280_REGISTER_PRESSUREDATA); adc_P >>= 4; var1 = ((int64_t)t_fine) - 128000; - var2 = var1 * var1 * (int64_t)_bme280_calib.dig_P6; - var2 = var2 + ((var1 * (int64_t)_bme280_calib.dig_P5) << 17); - var2 = var2 + (((int64_t)_bme280_calib.dig_P4) << 35); - var1 = ((var1 * var1 * (int64_t)_bme280_calib.dig_P3) >> 8) + ((var1 * (int64_t)_bme280_calib.dig_P2) << 12); - var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)_bme280_calib.dig_P1) >> 33; + 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; if (0 == var1) { - return 0; // avoid exception caused by division by zero + return 0; // avoid exception caused by division by zero } p = 1048576 - adc_P; p = (((p << 31) - var2) * 3125) / var1; - var1 = (((int64_t)_bme280_calib.dig_P9) * (p >> 13) * (p >> 13)) >> 25; - var2 = (((int64_t)_bme280_calib.dig_P8) * p) >> 19; - p = ((p + var1 + var2) >> 8) + (((int64_t)_bme280_calib.dig_P7) << 4); + 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); return (double)p / 25600.0; } -double bme280_readHumidity(void) +double Bme280ReadHumidity(void) { int32_t v_x1_u32r; -// Must be done first to get the t_fine variable set up -// bmp280_readTemperature(); + // Must be done first to get the t_fine variable set up + // Bme280ReadTemperature(); - int32_t adc_H = i2c_read16(bmpaddr, BME280_REGISTER_HUMIDDATA); + int32_t adc_H = I2cRead16(bmp_address, BME280_REGISTER_HUMIDDATA); v_x1_u32r = (t_fine - ((int32_t)76800)); - v_x1_u32r = (((((adc_H << 14) - (((int32_t)_bme280_calib.dig_H4) << 20) - - (((int32_t)_bme280_calib.dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) * - (((((((v_x1_u32r * ((int32_t)_bme280_calib.dig_H6)) >> 10) * - (((v_x1_u32r * ((int32_t)_bme280_calib.dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + - ((int32_t)2097152)) * ((int32_t)_bme280_calib.dig_H2) + 8192) >> 14)); + 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 = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * - ((int32_t)_bme280_calib.dig_H1)) >> 4)); + ((int32_t)Bme280CalibrationData.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; double h = (v_x1_u32r >> 12); - return h / 1024.0; + return h / 1024.0; } /*********************************************************************************************\ * BMP \*********************************************************************************************/ -double bmp_readTemperature(void) +double BmpReadTemperature(void) { double t = NAN; - switch (bmptype) { + switch (bmp_type) + { case BMP180_CHIPID: - t = bmp180_readTemperature(); + t = Bmp180ReadTemperature(); break; case BMP280_CHIPID: case BME280_CHIPID: - t = bmp280_readTemperature(); + t = Bme280ReadTemperature(); } - if (!isnan(t)) { - t = convertTemp(t); + if (!isnan(t)) + { + t = ConvertTemp(t); return t; } return 0; } -double bmp_readPressure(void) +double BmpReadPressure(void) { - switch (bmptype) { + double pressure = 0.0; + + switch (bmp_type) { case BMP180_CHIPID: - return bmp180_readPressure(); + pressure = Bmp180ReadPressure(); + break; case BMP280_CHIPID: case BME280_CHIPID: - return bmp280_readPressure(); + pressure = Bme280ReadPressure(); } - return 0; + if (pressure != 0.0) { +// bmp_sealevel = pressure / pow(1.0 - ((float)Settings.altitude / 44330.0), 5.255); // pow adds 8k to the code + bmp_sealevel = (pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; + } + return pressure; } -double bmp_readHumidity(void) +double BmpReadHumidity(void) { - switch (bmptype) { + switch (bmp_type) { case BMP180_CHIPID: case BMP280_CHIPID: break; case BME280_CHIPID: - return bme280_readHumidity(); + return Bme280ReadHumidity(); } return 0; } -boolean bmp_detect() +boolean BmpDetect() { - if (bmptype) { + if (bmp_type) { return true; } boolean success = false; - bmpaddr = BMP_ADDR; - bmptype = i2c_read8(bmpaddr, BMP_REGISTER_CHIPID); - if (!bmptype) { - bmpaddr--; - bmptype = i2c_read8(bmpaddr, BMP_REGISTER_CHIPID); + bmp_address = BMP_ADDR; + bmp_type = I2cRead8(bmp_address, BMP_REGISTER_CHIPID); + if (!bmp_type) { + bmp_address--; + bmp_type = I2cRead8(bmp_address, BMP_REGISTER_CHIPID); } - strcpy_P(bmpstype, PSTR("BMP")); - switch (bmptype) { + strcpy_P(bmp_types, PSTR("BMP")); + switch (bmp_type) { case BMP180_CHIPID: - success = bmp180_calibration(); - strcpy_P(bmpstype, PSTR("BMP180")); + success = Bmp180Calibration(); + strcpy_P(bmp_types, PSTR("BMP180")); break; case BMP280_CHIPID: - success = bmp280_calibrate(); - strcpy_P(bmpstype, PSTR("BMP280")); + success = Bmx280Calibrate(); + strcpy_P(bmp_types, PSTR("BMP280")); break; case BME280_CHIPID: - success = bme280_calibrate(); - strcpy_P(bmpstype, PSTR("BME280")); + success = Bmx280Calibrate(); + strcpy_P(bmp_types, PSTR("BME280")); } if (success) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "%s " D_FOUND_AT " 0x%x"), bmpstype, bmpaddr); - addLog(LOG_LEVEL_DEBUG); - } else { - bmptype = 0; + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "%s " D_FOUND_AT " 0x%x"), bmp_types, bmp_address); + AddLog(LOG_LEVEL_DEBUG); + } + else { + bmp_type = 0; } return success; } @@ -429,61 +411,71 @@ boolean bmp_detect() * Presentation \*********************************************************************************************/ -void bmp_mqttPresent(uint8_t* djson) +void MqttShowBmp(uint8_t *djson) { - if (!bmptype) { + if (!bmp_type) { return; } - char stemp1[10]; - char stemp2[10]; - char stemp3[10]; + char temperature[10]; + char pressure[10]; + char humidity[10]; + char sea_pressure[10]; + char sealevel[40]; - double t = bmp_readTemperature(); - double p = bmp_readPressure(); - double h = bmp_readHumidity(); - dtostrfd(t, sysCfg.flag.temperature_resolution, stemp1); - dtostrfd(p, sysCfg.flag.pressure_resolution, stemp2); - dtostrfd(h, sysCfg.flag.humidity_resolution, stemp3); - if (!strcmp(bmpstype,"BME280")) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_TEMPERATURE "\":%s, \"" D_HUMIDITY "\":%s, \"" D_PRESSURE "\":%s}"), - mqtt_data, bmpstype, stemp1, stemp3, stemp2); - } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_TEMPERATURE "\":%s, \"" D_PRESSURE "\":%s}"), - mqtt_data, bmpstype, stemp1, stemp2); + double t = BmpReadTemperature(); + double p = BmpReadPressure(); + double h = BmpReadHumidity(); + dtostrfd(t, Settings.flag.temperature_resolution, temperature); + dtostrfd(p, Settings.flag.pressure_resolution, pressure); + dtostrfd(h, Settings.flag.humidity_resolution, humidity); + + dtostrfd(bmp_sealevel, Settings.flag.pressure_resolution, sea_pressure); + snprintf_P(sealevel, sizeof(sealevel), PSTR(", \"" D_PRESSUREATSEALEVEL "\":%s"), sea_pressure); + if (BME280_CHIPID == bmp_type) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_TEMPERATURE "\":%s, \"" D_HUMIDITY "\":%s, \"" D_PRESSURE "\":%s%s}"), + mqtt_data, bmp_types, temperature, humidity, pressure, (Settings.altitude != 0) ? sealevel : ""); + } + else { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_TEMPERATURE "\":%s, \"" D_PRESSURE "\":%s%s}"), + mqtt_data, bmp_types, temperature, pressure, (Settings.altitude != 0) ? sealevel : ""); } *djson = 1; #ifdef USE_DOMOTICZ - domoticz_sensor3(stemp1, stemp3, stemp2); -#endif // USE_DOMOTICZ + DomoticzTempHumPressureSensor(temperature, humidity, pressure); +#endif // USE_DOMOTICZ } #ifdef USE_WEBSERVER -String bmp_webPresent() +String WebShowBmp() { String page = ""; - if (bmptype) { + if (bmp_type) { char stemp[10]; char sensor[80]; - double t_bmp = bmp_readTemperature(); - double p_bmp = bmp_readPressure(); - double h_bmp = bmp_readHumidity(); - dtostrfi(t_bmp, sysCfg.flag.temperature_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, bmpstype, stemp, tempUnit()); + double t = BmpReadTemperature(); + double p = BmpReadPressure(); + double h = BmpReadHumidity(); + dtostrfi(t, Settings.flag.temperature_resolution, stemp); + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, bmp_types, stemp, TempUnit()); page += sensor; - if (!strcmp(bmpstype,"BME280")) { - dtostrfi(h_bmp, sysCfg.flag.humidity_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, bmpstype, stemp); + if (BME280_CHIPID == bmp_type) { + dtostrfi(h, Settings.flag.humidity_resolution, stemp); + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, bmp_types, stemp); page += sensor; } - dtostrfi(p_bmp, sysCfg.flag.pressure_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_PRESSURE, bmpstype, stemp); + dtostrfi(p, Settings.flag.pressure_resolution, stemp); + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_PRESSURE, bmp_types, stemp); page += sensor; + if (Settings.altitude != 0) { + dtostrfi(bmp_sealevel, Settings.flag.pressure_resolution, stemp); + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_PRESSUREATSEALEVEL, bmp_types, stemp); + page += sensor; + } } return page; } -#endif // USE_WEBSERVER -#endif // USE_BMP -#endif // USE_I2C - +#endif // USE_WEBSERVER +#endif // USE_BMP +#endif // USE_I2C diff --git a/sonoff/xsns_counter.ino b/sonoff/xsns_counter.ino index 54e51c917..5712da198 100644 --- a/sonoff/xsns_counter.ino +++ b/sonoff/xsns_counter.ino @@ -21,57 +21,57 @@ * Counter sensors (water meters, electricity meters etc.) \*********************************************************************************************/ -unsigned long pTimeLast[MAX_COUNTERS]; // Last counter time in milli seconds +unsigned long last_counter_timer[MAX_COUNTERS]; // Last counter time in milli seconds -void counter_update(byte index) +void CounterUpdate(byte index) { - unsigned long pTime = millis() - pTimeLast[index -1]; - if (pTime > sysCfg.pCounterDebounce) { - pTimeLast[index -1] = millis(); - if (bitRead(sysCfg.pCounterType, index -1)) { - rtcMem.pCounter[index -1] = pTime; + unsigned long counter_debounce_time = millis() - last_counter_timer[index -1]; + if (counter_debounce_time > Settings.pulse_counter_debounce) { + last_counter_timer[index -1] = millis(); + if (bitRead(Settings.pulse_counter_type, index -1)) { + RtcSettings.pulse_counter[index -1] = counter_debounce_time; } else { - rtcMem.pCounter[index -1]++; + RtcSettings.pulse_counter[index -1]++; } // snprintf_P(log_data, sizeof(log_data), PSTR("CNTR: Interrupt %d"), index); -// addLog(LOG_LEVEL_DEBUG); +// AddLog(LOG_LEVEL_DEBUG); } } -void counter_update1() +void CounterUpdate1() { - counter_update(1); + CounterUpdate(1); } -void counter_update2() +void CounterUpdate2() { - counter_update(2); + CounterUpdate(2); } -void counter_update3() +void CounterUpdate3() { - counter_update(3); + CounterUpdate(3); } -void counter_update4() +void CounterUpdate4() { - counter_update(4); + CounterUpdate(4); } -void counter_savestate() +void CounterSaveState() { for (byte i = 0; i < MAX_COUNTERS; i++) { if (pin[GPIO_CNTR1 +i] < 99) { - sysCfg.pCounter[i] = rtcMem.pCounter[i]; + Settings.pulse_counter[i] = RtcSettings.pulse_counter[i]; } } } -void counter_init() +void CounterInit() { typedef void (*function) () ; - function counter_callbacks[] = { counter_update1, counter_update2, counter_update3, counter_update4 }; + function counter_callbacks[] = { CounterUpdate1, CounterUpdate2, CounterUpdate3, CounterUpdate4 }; for (byte i = 0; i < MAX_COUNTERS; i++) { if (pin[GPIO_CNTR1 +i] < 99) { @@ -85,24 +85,24 @@ void counter_init() * Presentation \*********************************************************************************************/ -void counter_mqttPresent(uint8_t* djson) +void MqttShowCounter(uint8_t* djson) { char stemp[16]; byte dsxflg = 0; for (byte i = 0; i < MAX_COUNTERS; i++) { if (pin[GPIO_CNTR1 +i] < 99) { - if (bitRead(sysCfg.pCounterType, i)) { - dtostrfd((double)rtcMem.pCounter[i] / 1000, 3, stemp); + if (bitRead(Settings.pulse_counter_type, i)) { + dtostrfd((double)RtcSettings.pulse_counter[i] / 1000, 3, stemp); } else { dsxflg++; - dtostrfd(rtcMem.pCounter[i], 0, stemp); + dtostrfd(RtcSettings.pulse_counter[i], 0, stemp); } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_COUNTER "%d\":%s"), mqtt_data, i +1, stemp); *djson = 1; #ifdef USE_DOMOTICZ if (1 == dsxflg) { - domoticz_sensor6(rtcMem.pCounter[i]); + DomoticzSensor(DZ_COUNT, RtcSettings.pulse_counter[i]); dsxflg++; } #endif // USE_DOMOTICZ @@ -114,7 +114,7 @@ void counter_mqttPresent(uint8_t* djson) const char HTTP_SNS_COUNTER[] PROGMEM = "" D_COUNTER "%d%s%s"; -String counter_webPresent() +String WebShowCounter() { String page = ""; char stemp[16]; @@ -122,12 +122,12 @@ String counter_webPresent() for (byte i = 0; i < MAX_COUNTERS; i++) { if (pin[GPIO_CNTR1 +i] < 99) { - if (bitRead(sysCfg.pCounterType, i)) { - dtostrfi((double)rtcMem.pCounter[i] / 1000, 3, stemp); + if (bitRead(Settings.pulse_counter_type, i)) { + dtostrfi((double)RtcSettings.pulse_counter[i] / 1000, 3, stemp); } else { - dtostrfi(rtcMem.pCounter[i], 0, stemp); + dtostrfi(RtcSettings.pulse_counter[i], 0, stemp); } - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_COUNTER, i+1, stemp, (bitRead(sysCfg.pCounterType, i)) ? " " D_UNIT_SECOND : ""); + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_COUNTER, i+1, stemp, (bitRead(Settings.pulse_counter_type, i)) ? " " D_UNIT_SECOND : ""); page += sensor; } } diff --git a/sonoff/xsns_dht.ino b/sonoff/xsns_dht.ino index e051a5425..cea2bf17f 100644 --- a/sonoff/xsns_dht.ino +++ b/sonoff/xsns_dht.ino @@ -27,9 +27,10 @@ \*********************************************************************************************/ #define DHT_MAX_SENSORS 3 +#define DHT_MAX_RETRY 8 #define MIN_INTERVAL 2000 -uint32_t dht_maxcycles; +uint32_t dht_max_cycles; uint8_t dht_data[5]; byte dht_sensors = 0; @@ -38,67 +39,72 @@ struct DHTSTRUCT { byte type; char stype[10]; uint32_t lastreadtime; - uint16_t lastresult; + uint8_t lastresult; float t; float h = 0; -} dht[DHT_MAX_SENSORS]; +} Dht[DHT_MAX_SENSORS]; -void dht_readPrep() +void DhtReadPrep() { for (byte i = 0; i < dht_sensors; i++) { - digitalWrite(dht[i].pin, HIGH); + digitalWrite(Dht[i].pin, HIGH); } } -uint32_t dht_expectPulse(byte sensor, bool level) +uint32_t DhtExpectPulse(byte sensor, bool level) { uint32_t count = 0; - while (digitalRead(dht[sensor].pin) == level) { - if (count++ >= dht_maxcycles) { + while (digitalRead(Dht[sensor].pin) == level) { + if (count++ >= dht_max_cycles) { return 0; } } return count; } -void dht_read(byte sensor) +void DhtRead(byte sensor) { uint32_t cycles[80]; uint32_t currenttime = millis(); - if ((currenttime - dht[sensor].lastreadtime) < 2000) { + if ((currenttime - Dht[sensor].lastreadtime) < MIN_INTERVAL) { return; } - dht[sensor].lastreadtime = currenttime; + Dht[sensor].lastreadtime = currenttime; dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; -// digitalWrite(dht[sensor].pin, HIGH); +// digitalWrite(Dht[sensor].pin, HIGH); // delay(250); - pinMode(dht[sensor].pin, OUTPUT); - digitalWrite(dht[sensor].pin, LOW); + if (Dht[sensor].lastresult > DHT_MAX_RETRY) { + Dht[sensor].lastresult = 0; + digitalWrite(Dht[sensor].pin, HIGH); // Retry read prep + delay(250); + } + pinMode(Dht[sensor].pin, OUTPUT); + digitalWrite(Dht[sensor].pin, LOW); delay(20); noInterrupts(); - digitalWrite(dht[sensor].pin, HIGH); + digitalWrite(Dht[sensor].pin, HIGH); delayMicroseconds(40); - pinMode(dht[sensor].pin, INPUT_PULLUP); + pinMode(Dht[sensor].pin, INPUT_PULLUP); delayMicroseconds(10); - if (0 == dht_expectPulse(sensor, LOW)) { - addLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); - dht[sensor].lastresult++; + if (0 == DhtExpectPulse(sensor, LOW)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); + Dht[sensor].lastresult++; return; } - if (0 == dht_expectPulse(sensor, HIGH)) { - addLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); - dht[sensor].lastresult++; + if (0 == DhtExpectPulse(sensor, HIGH)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); + Dht[sensor].lastresult++; return; } for (int i = 0; i < 80; i += 2) { - cycles[i] = dht_expectPulse(sensor, LOW); - cycles[i+1] = dht_expectPulse(sensor, HIGH); + cycles[i] = DhtExpectPulse(sensor, LOW); + cycles[i+1] = DhtExpectPulse(sensor, HIGH); } interrupts(); @@ -106,8 +112,8 @@ void dht_read(byte sensor) uint32_t lowCycles = cycles[2*i]; uint32_t highCycles = cycles[2*i+1]; if ((0 == lowCycles) || (0 == highCycles)) { - addLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); - dht[sensor].lastresult++; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); + Dht[sensor].lastresult++; return; } dht_data[i/8] <<= 1; @@ -118,36 +124,36 @@ void dht_read(byte sensor) snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DHT D_RECEIVED " %02X, %02X, %02X, %02X, %02X =? %02X"), dht_data[0], dht_data[1], dht_data[2], dht_data[3], dht_data[4], (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF); - addLog(LOG_LEVEL_DEBUG); + AddLog(LOG_LEVEL_DEBUG); if (dht_data[4] == ((dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF)) { - dht[sensor].lastresult = 0; + Dht[sensor].lastresult = 0; } else { - addLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE)); - dht[sensor].lastresult++; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE)); + Dht[sensor].lastresult++; } } -boolean dht_readTempHum(byte sensor, float &t, float &h) +boolean DhtReadTempHum(byte sensor, float &t, float &h) { - if (!dht[sensor].h) { + if (!Dht[sensor].h) { t = NAN; h = NAN; } else { - if (dht[sensor].lastresult > 8) { // Reset after 8 misses - dht[sensor].t = NAN; - dht[sensor].h = NAN; + if (Dht[sensor].lastresult > DHT_MAX_RETRY) { // Reset after 8 misses + Dht[sensor].t = NAN; + Dht[sensor].h = NAN; } - t = dht[sensor].t; - h = dht[sensor].h; + t = Dht[sensor].t; + h = Dht[sensor].h; } - dht_read(sensor); - if (!dht[sensor].lastresult) { - switch (dht[sensor].type) { + DhtRead(sensor); + if (!Dht[sensor].lastresult) { + switch (Dht[sensor].type) { case GPIO_DHT11: h = dht_data[0]; - t = convertTemp(dht_data[2]); + t = ConvertTemp(dht_data[2]); break; case GPIO_DHT22: case GPIO_DHT21: @@ -162,52 +168,52 @@ boolean dht_readTempHum(byte sensor, float &t, float &h) if (dht_data[2] & 0x80) { t *= -1; } - t = convertTemp(t); + t = ConvertTemp(t); break; } if (!isnan(t)) { - dht[sensor].t = t; + Dht[sensor].t = t; } if (!isnan(h)) { - dht[sensor].h = h; + Dht[sensor].h = h; } } return (!isnan(t) && !isnan(h)); } -boolean dht_setup(byte pin, byte type) +boolean DhtSetup(byte pin, byte type) { boolean success = false; if (dht_sensors < DHT_MAX_SENSORS) { - dht[dht_sensors].pin = pin; - dht[dht_sensors].type = type; + Dht[dht_sensors].pin = pin; + Dht[dht_sensors].type = type; dht_sensors++; success = true; } return success; } -void dht_init() +void DhtInit() { - dht_maxcycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for reading pulses from DHT sensor. + dht_max_cycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for reading pulses from DHT sensor. for (byte i = 0; i < dht_sensors; i++) { - pinMode(dht[i].pin, INPUT_PULLUP); - dht[i].lastreadtime = 0; - dht[i].lastresult = 0; - switch (dht[i].type) { + pinMode(Dht[i].pin, INPUT_PULLUP); + Dht[i].lastreadtime = 0; + Dht[i].lastresult = 0; + switch (Dht[i].type) { case GPIO_DHT11: - strcpy_P(dht[i].stype, PSTR("DHT11")); + strcpy_P(Dht[i].stype, PSTR("DHT11")); break; case GPIO_DHT21: - strcpy_P(dht[i].stype, PSTR("AM2301")); + strcpy_P(Dht[i].stype, PSTR("AM2301")); break; case GPIO_DHT22: - strcpy_P(dht[i].stype, PSTR("DHT22")); + strcpy_P(Dht[i].stype, PSTR("DHT22")); } if (dht_sensors > 1) { - snprintf_P(dht[i].stype, sizeof(dht[i].stype), PSTR("%s-%02d"), dht[i].stype, dht[i].pin); + snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s-%02d"), Dht[i].stype, Dht[i].pin); } } } @@ -216,7 +222,7 @@ void dht_init() * Presentation \*********************************************************************************************/ -void dht_mqttPresent(uint8_t* djson) +void MqttShowDht(uint8_t* djson) { char stemp1[10]; char stemp2[10]; @@ -225,14 +231,14 @@ void dht_mqttPresent(uint8_t* djson) byte dsxflg = 0; for (byte i = 0; i < dht_sensors; i++) { - if (dht_readTempHum(i, t, h)) { // Read temperature - dtostrfd(t, sysCfg.flag.temperature_resolution, stemp1); - dtostrfd(h, sysCfg.flag.humidity_resolution, stemp2); - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, dht[i].stype, stemp1, stemp2); + if (DhtReadTempHum(i, t, h)) { // Read temperature + dtostrfd(t, Settings.flag.temperature_resolution, stemp1); + dtostrfd(h, Settings.flag.humidity_resolution, stemp2); + snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, Dht[i].stype, stemp1, stemp2); *djson = 1; #ifdef USE_DOMOTICZ if (!dsxflg) { - domoticz_sensor2(stemp1, stemp2); + DomoticzTempHumSensor(stemp1, stemp2); dsxflg++; } #endif // USE_DOMOTICZ @@ -241,7 +247,7 @@ void dht_mqttPresent(uint8_t* djson) } #ifdef USE_WEBSERVER -String dht_webPresent() +String WebShowDht() { String page = ""; char stemp[10]; @@ -250,12 +256,12 @@ String dht_webPresent() float h; for (byte i = 0; i < dht_sensors; i++) { - if (dht_readTempHum(i, t, h)) { - dtostrfi(t, sysCfg.flag.temperature_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, dht[i].stype, stemp, tempUnit()); + if (DhtReadTempHum(i, t, h)) { + dtostrfi(t, Settings.flag.temperature_resolution, stemp); + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, Dht[i].stype, stemp, TempUnit()); page += sensor; - dtostrfi(h, sysCfg.flag.humidity_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, dht[i].stype, stemp); + dtostrfi(h, Settings.flag.humidity_resolution, stemp); + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, Dht[i].stype, stemp); page += sensor; } } diff --git a/sonoff/xsns_ds18b20.ino b/sonoff/xsns_ds18b20.ino index 5940dfdbd..5b003a6f6 100644 --- a/sonoff/xsns_ds18b20.ino +++ b/sonoff/xsns_ds18b20.ino @@ -24,10 +24,10 @@ * Source: Marinus vd Broek https://github.com/ESP8266nu/ESPEasy and AlexTransit (CRC) \*********************************************************************************************/ -float dsb_mt = 0; -uint16_t dsb_lastresult = 0; +float ds18b20_last_temperature = 0; +uint16_t ds18b20_last_result = 0; -uint8_t dsb_reset() +uint8_t Ds18b20Reset() { uint8_t r; uint8_t retries = 125; @@ -49,7 +49,7 @@ uint8_t dsb_reset() return r; } -uint8_t dsb_read_bit(void) +uint8_t Ds18b20ReadBit(void) { uint8_t r; @@ -63,20 +63,20 @@ uint8_t dsb_read_bit(void) return r; } -uint8_t dsb_read(void) +uint8_t Ds18b20Read(void) { - uint8_t bitMask; + uint8_t bit_mask; uint8_t r = 0; - for (bitMask = 0x01; bitMask; bitMask <<= 1) { - if (dsb_read_bit()) { - r |= bitMask; + for (bit_mask = 1; bit_mask; bit_mask <<= 1) { + if (Ds18b20ReadBit()) { + r |= bit_mask; } } return r; } -void dsb_write_bit(uint8_t v) +void Ds18b20WriteBit(uint8_t v) { if (v & 1) { digitalWrite(pin[GPIO_DSB], LOW); @@ -93,16 +93,16 @@ void dsb_write_bit(uint8_t v) } } -void dsb_write(uint8_t ByteToWrite) +void Ds18b20Write(uint8_t byte_to_write) { - uint8_t bitMask; + uint8_t bit_mask; - for (bitMask = 0x01; bitMask; bitMask <<= 1) { - dsb_write_bit((bitMask & ByteToWrite) ? 1 : 0); + for (bit_mask = 1; bit_mask; bit_mask <<= 1) { + Ds18b20WriteBit((bit_mask & byte_to_write) ? 1 : 0); } } -uint8 dsb_crc(uint8 inp, uint8 crc) +uint8 Ds18b20Crc(uint8 inp, uint8 crc) { inp ^= crc; crc = 0; @@ -117,66 +117,66 @@ uint8 dsb_crc(uint8 inp, uint8 crc) return crc; } -void dsb_readTempPrep() +void Ds18b20ReadTempPrep() { - dsb_reset(); - dsb_write(0xCC); // Skip ROM - dsb_write(0x44); // Start conversion + Ds18b20Reset(); + Ds18b20Write(0xCC); // Skip ROM + Ds18b20Write(0x44); // Start conversion } -boolean dsb_readTemp(float &t) +boolean Ds18b20ReadTemperature(float &t) { int16_t DSTemp; byte msb, lsb, crc, sign = 1; - if (!dsb_mt) { + if (!ds18b20_last_temperature) { t = NAN; } else { - dsb_lastresult++; - if (dsb_lastresult > 8) { // Reset after 8 misses - dsb_mt = NAN; + ds18b20_last_result++; + if (ds18b20_last_result > 8) { // Reset after 8 misses + ds18b20_last_temperature = NAN; } - t = dsb_mt; + t = ds18b20_last_temperature; } - if (!dsb_read_bit()) { //check measurement end - addLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_BUSY)); + if (!Ds18b20ReadBit()) { //check measurement end + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_BUSY)); return !isnan(t); } /* - dsb_reset(); - dsb_write(0xCC); // Skip ROM - dsb_write(0x44); // Start conversion + Ds18b20Reset(); + Ds18b20Write(0xCC); // Skip ROM + Ds18b20Write(0x44); // Start conversion delay(800); */ - dsb_reset(); - dsb_write(0xCC); // Skip ROM - dsb_write(0xBE); // Read scratchpad - lsb = dsb_read(); - msb = dsb_read(); - crc = dsb_crc(lsb, crc); - crc = dsb_crc(msb, crc); - crc = dsb_crc(dsb_read(), crc); - crc = dsb_crc(dsb_read(), crc); - crc = dsb_crc(dsb_read(), crc); - crc = dsb_crc(dsb_read(), crc); - crc = dsb_crc(dsb_read(), crc); - crc = dsb_crc(dsb_read(), crc); - crc = dsb_crc(dsb_read(), crc); - dsb_reset(); + Ds18b20Reset(); + Ds18b20Write(0xCC); // Skip ROM + Ds18b20Write(0xBE); // Read scratchpad + lsb = Ds18b20Read(); + msb = Ds18b20Read(); + crc = Ds18b20Crc(lsb, crc); + crc = Ds18b20Crc(msb, crc); + crc = Ds18b20Crc(Ds18b20Read(), crc); + crc = Ds18b20Crc(Ds18b20Read(), crc); + crc = Ds18b20Crc(Ds18b20Read(), crc); + crc = Ds18b20Crc(Ds18b20Read(), crc); + crc = Ds18b20Crc(Ds18b20Read(), crc); + crc = Ds18b20Crc(Ds18b20Read(), crc); + crc = Ds18b20Crc(Ds18b20Read(), crc); + Ds18b20Reset(); if (crc) { //check crc - addLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); } else { DSTemp = (msb << 8) + lsb; if (DSTemp > 2047) { DSTemp = (~DSTemp) +1; sign = -1; } - t = convertTemp((float)sign * DSTemp * 0.0625); - dsb_lastresult = 0; + t = ConvertTemp((float)sign * DSTemp * 0.0625); + ds18b20_last_result = 0; } if (!isnan(t)) { - dsb_mt = t; + ds18b20_last_temperature = t; } return !isnan(t); } @@ -185,37 +185,37 @@ boolean dsb_readTemp(float &t) * Presentation \*********************************************************************************************/ -void dsb_mqttPresent(uint8_t* djson) +void MqttShowDs18b20(uint8_t* djson) { char stemp1[10]; float t; - if (dsb_readTemp(t)) { // Check if read failed - dtostrfd(t, sysCfg.flag.temperature_resolution, stemp1); + if (Ds18b20ReadTemperature(t)) { // Check if read failed + dtostrfd(t, Settings.flag.temperature_resolution, stemp1); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"DS18B20\":{\"" D_TEMPERATURE "\":%s}"), mqtt_data, stemp1); *djson = 1; #ifdef USE_DOMOTICZ - domoticz_sensor1(stemp1); + DomoticzSensor(DZ_TEMP, stemp1); #endif // USE_DOMOTICZ } } #ifdef USE_WEBSERVER -String dsb_webPresent() +String WebShowDs18b20() { // Needs TelePeriod to refresh data (Do not do it here as it takes too much time) String page = ""; float st; - if (dsb_readTemp(st)) { // Check if read failed + if (Ds18b20ReadTemperature(st)) { // Check if read failed char stemp[10]; char sensor[80]; - dtostrfi(st, sysCfg.flag.temperature_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, "DS18B20", stemp, tempUnit()); + dtostrfi(st, Settings.flag.temperature_resolution, stemp); + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, "DS18B20", stemp, TempUnit()); page += sensor; } - dsb_readTempPrep(); + Ds18b20ReadTempPrep(); return page; } #endif // USE_WEBSERVER diff --git a/sonoff/xsns_ds18x20.ino b/sonoff/xsns_ds18x20.ino index 3e20ecef3..2733ba9ab 100644 --- a/sonoff/xsns_ds18x20.ino +++ b/sonoff/xsns_ds18x20.ino @@ -36,64 +36,62 @@ OneWire *ds = NULL; -uint8_t ds18x20_addr[DS18X20_MAX_SENSORS][8]; -uint8_t ds18x20_idx[DS18X20_MAX_SENSORS]; -uint8_t ds18x20_snsrs = 0; -char dsbstype[9]; +uint8_t ds18x20_address[DS18X20_MAX_SENSORS][8]; +uint8_t ds18x20_index[DS18X20_MAX_SENSORS]; +uint8_t ds18x20_sensors = 0; +char ds18x20_types[9]; -void ds18x20_init() +void Ds18x20Init() { ds = new OneWire(pin[GPIO_DSB]); } -void ds18x20_search() +void Ds18x20Search() { uint8_t num_sensors=0; uint8_t sensor = 0; - uint8_t i; ds->reset_search(); for (num_sensors = 0; num_sensors < DS18X20_MAX_SENSORS; num_sensors) { - if (!ds->search(ds18x20_addr[num_sensors])) { + if (!ds->search(ds18x20_address[num_sensors])) { ds->reset_search(); break; } // If CRC Ok and Type DS18S20, DS18B20 or MAX31850 - if ((OneWire::crc8(ds18x20_addr[num_sensors], 7) == ds18x20_addr[num_sensors][7]) && - ((ds18x20_addr[num_sensors][0]==DS18S20_CHIPID) || (ds18x20_addr[num_sensors][0]==DS18B20_CHIPID) || (ds18x20_addr[num_sensors][0]==MAX31850_CHIPID))) { + if ((OneWire::crc8(ds18x20_address[num_sensors], 7) == ds18x20_address[num_sensors][7]) && + ((ds18x20_address[num_sensors][0]==DS18S20_CHIPID) || (ds18x20_address[num_sensors][0]==DS18B20_CHIPID) || (ds18x20_address[num_sensors][0]==MAX31850_CHIPID))) { num_sensors++; } } - for (int i = 0; i < num_sensors; i++) { - ds18x20_idx[i] = i; + for (byte i = 0; i < num_sensors; i++) { + ds18x20_index[i] = i; } - for (int i = 0; i < num_sensors; i++) { - for (int j = i + 1; j < num_sensors; j++) { - if (uint32_t(ds18x20_addr[ds18x20_idx[i]]) > uint32_t(ds18x20_addr[ds18x20_idx[j]])) { - std::swap(ds18x20_idx[i], ds18x20_idx[j]); + for (byte i = 0; i < num_sensors; i++) { + for (byte j = i + 1; j < num_sensors; j++) { + if (uint32_t(ds18x20_address[ds18x20_index[i]]) > uint32_t(ds18x20_address[ds18x20_index[j]])) { + std::swap(ds18x20_index[i], ds18x20_index[j]); } } } - ds18x20_snsrs = num_sensors; + ds18x20_sensors = num_sensors; } -uint8_t ds18x20_sensors() +uint8_t Ds18x20Sensors() { - return ds18x20_snsrs; + return ds18x20_sensors; } -String ds18x20_address(uint8_t sensor) +String Ds18x20Addresses(uint8_t sensor) { - char addrStr[20]; - uint8_t i; + char address[20]; - for (i = 0; i < 8; i++) { - sprintf(addrStr+2*i, "%02X", ds18x20_addr[ds18x20_idx[sensor]][i]); + for (byte i = 0; i < 8; i++) { + sprintf(address+2*i, "%02X", ds18x20_address[ds18x20_index[sensor]][i]); } - return String(addrStr); + return String(address); } -void ds18x20_convert() +void Ds18x20Convert() { ds->reset(); ds->write(W1_SKIP_ROM); // Address all Sensors on Bus @@ -101,40 +99,25 @@ void ds18x20_convert() // delay(750); // 750ms should be enough for 12bit conv } -boolean ds18x20_read(uint8_t sensor, float &t) +boolean Ds18x20Read(uint8_t sensor, float &t) { byte data[12]; int8_t sign = 1; - uint8_t i = 0; float temp9 = 0.0; uint8_t present = 0; t = NAN; ds->reset(); - ds->select(ds18x20_addr[ds18x20_idx[sensor]]); + ds->select(ds18x20_address[ds18x20_index[sensor]]); ds->write(W1_READ_SCRATCHPAD); // Read Scratchpad - for (i = 0; i < 9; i++) { + for (byte i = 0; i < 9; i++) { data[i] = ds->read(); } if (OneWire::crc8(data, 8) == data[8]) { - switch(ds18x20_addr[ds18x20_idx[sensor]][0]) { + switch(ds18x20_address[ds18x20_index[sensor]][0]) { case DS18S20_CHIPID: // DS18S20 -/* -// App_note AN162.pdf page 9 - int temp_lsb, temp_msb; - temp_msb = data[1]; // Sign byte + lsbit - temp_lsb = data[0]; // Temp data plus lsb - if (temp_msb <= 0x80) temp_lsb = (temp_lsb/2); // Shift to get whole degree - temp_msb = temp_msb & 0x80; // Mask all but the sign bit - if (temp_msb >= 0x80) { // Negative temperature - temp_lsb = (~temp_lsb)+1; // Twos complement - temp_lsb = (temp_lsb/2); // Shift to get whole degree - temp_lsb = ((-1)*temp_lsb); // Add sign bit - } - t = (int)temp_lsb; // Temperature in whole degree -*/ if (data[1] > 0x80) { data[0] = (~data[0]) +1; sign = -1; // App-Note fix possible sign error @@ -144,7 +127,7 @@ boolean ds18x20_read(uint8_t sensor, float &t) } else { temp9 = (data[0] >> 1) * sign; } - t = convertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); + t = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); break; case DS18B20_CHIPID: // DS18B20 case MAX31850_CHIPID: // MAX31850 @@ -153,7 +136,7 @@ boolean ds18x20_read(uint8_t sensor, float &t) temp12 = (~temp12) +1; sign = -1; } - t = convertTemp(sign * temp12 * 0.0625); + t = ConvertTemp(sign * temp12 * 0.0625); break; } } @@ -164,33 +147,33 @@ boolean ds18x20_read(uint8_t sensor, float &t) * Presentation \*********************************************************************************************/ -void ds18x20_type(uint8_t sensor) +void Ds18x20Type(uint8_t sensor) { - strcpy_P(dsbstype, PSTR("DS18x20")); - switch(ds18x20_addr[ds18x20_idx[sensor]][0]) { + strcpy_P(ds18x20_types, PSTR("DS18x20")); + switch(ds18x20_address[ds18x20_index[sensor]][0]) { case DS18S20_CHIPID: - strcpy_P(dsbstype, PSTR("DS18S20")); + strcpy_P(ds18x20_types, PSTR("DS18S20")); break; case DS18B20_CHIPID: - strcpy_P(dsbstype, PSTR("DS18B20")); + strcpy_P(ds18x20_types, PSTR("DS18B20")); break; case MAX31850_CHIPID: - strcpy_P(dsbstype, PSTR("MAX31850")); + strcpy_P(ds18x20_types, PSTR("MAX31850")); break; } } -void ds18x20_mqttPresent(uint8_t* djson) +void MqttShowDs18x20(uint8_t* djson) { char stemp1[10]; char stemp2[10]; float t; byte dsxflg = 0; - for (byte i = 0; i < ds18x20_sensors(); i++) { - if (ds18x20_read(i, t)) { // Check if read failed - ds18x20_type(i); - dtostrfd(t, sysCfg.flag.temperature_resolution, stemp2); + for (byte i = 0; i < Ds18x20Sensors(); i++) { + if (Ds18x20Read(i, t)) { // Check if read failed + Ds18x20Type(i); + dtostrfd(t, Settings.flag.temperature_resolution, stemp2); if (!dsxflg) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"DS18x20\":{"), mqtt_data); *djson = 1; @@ -198,10 +181,12 @@ void ds18x20_mqttPresent(uint8_t* djson) } dsxflg++; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"DS%d\":{\"" D_TYPE "\":\"%s\", \"" D_ADDRESS "\":\"%s\", \"" D_TEMPERATURE "\":%s}"), - mqtt_data, stemp1, i +1, dsbstype, ds18x20_address(i).c_str(), stemp2); + mqtt_data, stemp1, i +1, ds18x20_types, Ds18x20Addresses(i).c_str(), stemp2); strcpy(stemp1, ", "); #ifdef USE_DOMOTICZ - if (1 == dsxflg) domoticz_sensor1(stemp2); + if (1 == dsxflg) { + DomoticzSensor(DZ_TEMP, stemp2); + } #endif // USE_DOMOTICZ } } @@ -211,7 +196,7 @@ void ds18x20_mqttPresent(uint8_t* djson) } #ifdef USE_WEBSERVER -String ds18x20_webPresent() +String WebShowDs18x20() { String page = ""; char stemp[10]; @@ -219,17 +204,17 @@ String ds18x20_webPresent() char sensor[80]; float t; - for (byte i = 0; i < ds18x20_sensors(); i++) { - if (ds18x20_read(i, t)) { // Check if read failed - ds18x20_type(i); - dtostrfi(t, sysCfg.flag.temperature_resolution, stemp); - snprintf_P(stemp2, sizeof(stemp2), PSTR("%s-%d"), dsbstype, i +1); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, stemp2, stemp, tempUnit()); + for (byte i = 0; i < Ds18x20Sensors(); i++) { + if (Ds18x20Read(i, t)) { // Check if read failed + Ds18x20Type(i); + dtostrfi(t, Settings.flag.temperature_resolution, stemp); + snprintf_P(stemp2, sizeof(stemp2), PSTR("%s-%d"), ds18x20_types, i +1); + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, stemp2, stemp, TempUnit()); page += sensor; } } - ds18x20_search(); // Check for changes in sensors number - ds18x20_convert(); // Start Conversion, takes up to one second + Ds18x20Search(); // Check for changes in sensors number + Ds18x20Convert(); // Start Conversion, takes up to one second return page; } #endif // USE_WEBSERVER diff --git a/sonoff/xsns_hlw8012.ino b/sonoff/xsns_hlw8012.ino index cf3f494e6..816b2c2ee 100644 --- a/sonoff/xsns_hlw8012.ino +++ b/sonoff/xsns_hlw8012.ino @@ -33,12 +33,25 @@ #define HLW_POWER_PROBE_TIME 10 // Number of seconds to probe for power before deciding none used -byte hlw_pminflg = 0; -byte hlw_pmaxflg = 0; -byte hlw_uminflg = 0; -byte hlw_umaxflg = 0; -byte hlw_iminflg = 0; -byte hlw_imaxflg = 0; +enum Hlw8012Commands { + CMND_POWERLOW, CMND_POWERHIGH, CMND_VOLTAGELOW, CMND_VOLTAGEHIGH, CMND_CURRENTLOW, CMND_CURRENTHIGH, + CMND_HLWPCAL, CMND_HLWPSET, CMND_HLWUCAL, CMND_HLWUSET, CMND_HLWICAL, CMND_HLWISET, + CMND_ENERGYRESET, CMND_MAXENERGY, CMND_MAXENERGYSTART, + CMND_MAXPOWER, CMND_MAXPOWERHOLD, CMND_MAXPOWERWINDOW, + CMND_SAFEPOWER, CMND_SAFEPOWERHOLD, CMND_SAFEPOWERWINDOW }; +const char kHlw8012Commands[] PROGMEM = + D_CMND_POWERLOW "|" D_CMND_POWERHIGH "|" D_CMND_VOLTAGELOW "|" D_CMND_VOLTAGEHIGH "|" D_CMND_CURRENTLOW "|" D_CMND_CURRENTHIGH "|" + D_CMND_HLWPCAL "|" D_CMND_HLWPSET "|" D_CMND_HLWUCAL "|" D_CMND_HLWUSET "|" D_CMND_HLWICAL "|" D_CMND_HLWISET "|" + D_CMND_ENERGYRESET "|" D_CMND_MAXENERGY "|" D_CMND_MAXENERGYSTART "|" + D_CMND_MAXPOWER "|" D_CMND_MAXPOWERHOLD "|" D_CMND_MAXPOWERWINDOW "|" + D_CMND_SAFEPOWER "|" D_CMND_SAFEPOWERHOLD "|" D_CMND_SAFEPOWERWINDOW ; + +byte hlw_pmin_flag = 0; +byte hlw_pmax_flag = 0; +byte hlw_umin_flag = 0; +byte hlw_umax_flag = 0; +byte hlw_imin_flag = 0; +byte hlw_imax_flag = 0; byte power_steady_cntr; byte hlw_mkwh_state = 0; @@ -49,59 +62,59 @@ byte hlw_mkwh_state = 0; uint16_t hlw_mplw_counter = 0; #endif // FEATURE_POWER_LIMIT -byte hlw_SELflag; +byte hlw_select_ui_flag; byte hlw_load_off; byte hlw_cf1_timer; byte hlw_fifth_second; byte hlw_startup; -unsigned long hlw_cf_plen; -unsigned long hlw_cf_last; -unsigned long hlw_cf1_plen; -unsigned long hlw_cf1_last; -unsigned long hlw_cf1_ptot; -unsigned long hlw_cf1_pcnt; -unsigned long hlw_cf1u_plen; -unsigned long hlw_cf1i_plen; -unsigned long hlw_Ecntr; -unsigned long hlw_EDcntr; +unsigned long hlw_cf_pulse_length; +unsigned long hlw_cf_pulse_last_time; +unsigned long hlw_cf1_pulse_length; +unsigned long hlw_cf1_pulse_last_time; +unsigned long hlw_cf1_summed_pulse_length; +unsigned long hlw_cf1_pulse_counter; +unsigned long hlw_cf1_voltage_pulse_length; +unsigned long hlw_cf1_current_pulse_length; +unsigned long hlw_energy_counter; +unsigned long hlw_energy_period_counter; unsigned long hlw_kWhtoday; uint32_t hlw_lasttime; -unsigned long hlw_cf1u_pcntmax; -unsigned long hlw_cf1i_pcntmax; +unsigned long hlw_cf1_voltage_max_pulse_counter; +unsigned long hlw_cf1_current_max_pulse_counter; Ticker tickerHLW; #ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves exception -void hlw_cf_interrupt() ICACHE_RAM_ATTR; -void hlw_cf1_interrupt() ICACHE_RAM_ATTR; +void HlwCfInterrupt() ICACHE_RAM_ATTR; +void HlwCf1Interrupt() ICACHE_RAM_ATTR; #endif // USE_WS2812_DMA -void hlw_cf_interrupt() // Service Power +void HlwCfInterrupt() // Service Power { unsigned long us = micros(); if (hlw_load_off) { // Restart plen measurement - hlw_cf_last = us; + hlw_cf_pulse_last_time = us; hlw_load_off = 0; } else { - hlw_cf_plen = us - hlw_cf_last; - hlw_cf_last = us; - hlw_EDcntr++; - hlw_Ecntr++; + hlw_cf_pulse_length = us - hlw_cf_pulse_last_time; + hlw_cf_pulse_last_time = us; + hlw_energy_period_counter++; + hlw_energy_counter++; } } -void hlw_cf1_interrupt() // Service Voltage and Current +void HlwCf1Interrupt() // Service Voltage and Current { unsigned long us = micros(); - hlw_cf1_plen = us - hlw_cf1_last; - hlw_cf1_last = us; + hlw_cf1_pulse_length = us - hlw_cf1_pulse_last_time; + hlw_cf1_pulse_last_time = us; if ((hlw_cf1_timer > 2) && (hlw_cf1_timer < 8)) { // Allow for 300 mSec set-up time and measure for up to 1 second - hlw_cf1_ptot += hlw_cf1_plen; - hlw_cf1_pcnt++; - if (10 == hlw_cf1_pcnt) { + hlw_cf1_summed_pulse_length += hlw_cf1_pulse_length; + hlw_cf1_pulse_counter++; + if (10 == hlw_cf1_pulse_counter) { hlw_cf1_timer = 8; // We need up to ten samples within 1 second (low current could take up to 0.3 second) } } @@ -116,71 +129,71 @@ void hlw_200mS() if (5 == hlw_fifth_second) { hlw_fifth_second = 0; - if (hlw_EDcntr) { - hlw_len = 10000 / hlw_EDcntr; - hlw_EDcntr = 0; + if (hlw_energy_period_counter) { + hlw_len = 10000 / hlw_energy_period_counter; + hlw_energy_period_counter = 0; if (hlw_len) { - hlw_temp = ((HLW_PREF * sysCfg.hlw_pcal) / hlw_len) / 36; + hlw_temp = ((HLW_PREF * Settings.hlw_power_calibration) / hlw_len) / 36; hlw_kWhtoday += hlw_temp; - rtcMem.hlw_kWhtoday = hlw_kWhtoday; + RtcSettings.hlw_kWhtoday = hlw_kWhtoday; } } - if (rtcTime.Valid) { - if (rtc_loctime() == rtc_midnight()) { - sysCfg.hlw_kWhyesterday = hlw_kWhtoday; - sysCfg.hlw_kWhtotal += (hlw_kWhtoday / 1000); - rtcMem.hlw_kWhtotal = sysCfg.hlw_kWhtotal; + if (RtcTime.valid) { + if (LocalTime() == Midnight()) { + Settings.hlw_kWhyesterday = hlw_kWhtoday; + Settings.hlw_kWhtotal += (hlw_kWhtoday / 1000); + RtcSettings.hlw_kWhtotal = Settings.hlw_kWhtotal; hlw_kWhtoday = 0; - rtcMem.hlw_kWhtoday = hlw_kWhtoday; + RtcSettings.hlw_kWhtoday = hlw_kWhtoday; hlw_mkwh_state = 3; } - if ((rtcTime.Hour == sysCfg.hlw_mkwhs) && (3 == hlw_mkwh_state)) { + if ((RtcTime.hour == Settings.hlw_mkwhs) && (3 == hlw_mkwh_state)) { hlw_mkwh_state = 0; } - if (hlw_startup && (rtcTime.DayOfYear == sysCfg.hlw_kWhdoy)) { - hlw_kWhtoday = sysCfg.hlw_kWhtoday; - rtcMem.hlw_kWhtoday = hlw_kWhtoday; + if (hlw_startup && (RtcTime.day_of_year == Settings.hlw_kWhdoy)) { + hlw_kWhtoday = Settings.hlw_kWhtoday; + RtcSettings.hlw_kWhtoday = hlw_kWhtoday; hlw_startup = 0; } } } - if (micros() - hlw_cf_last > (HLW_POWER_PROBE_TIME * 1000000)) { - hlw_cf_plen = 0; // No load for some time + if (micros() - hlw_cf_pulse_last_time > (HLW_POWER_PROBE_TIME * 1000000)) { + hlw_cf_pulse_length = 0; // No load for some time hlw_load_off = 1; } hlw_cf1_timer++; if (hlw_cf1_timer >= 8) { hlw_cf1_timer = 0; - hlw_SELflag = (hlw_SELflag) ? 0 : 1; - digitalWrite(pin[GPIO_HLW_SEL], hlw_SELflag); + hlw_select_ui_flag = (hlw_select_ui_flag) ? 0 : 1; + digitalWrite(pin[GPIO_HLW_SEL], hlw_select_ui_flag); - if (hlw_cf1_pcnt) { - hlw_cf1_plen = hlw_cf1_ptot / hlw_cf1_pcnt; + if (hlw_cf1_pulse_counter) { + hlw_cf1_pulse_length = hlw_cf1_summed_pulse_length / hlw_cf1_pulse_counter; } else { - hlw_cf1_plen = 0; + hlw_cf1_pulse_length = 0; } - if (hlw_SELflag) { - hlw_cf1u_plen = hlw_cf1_plen; - hlw_cf1u_pcntmax = hlw_cf1_pcnt; + if (hlw_select_ui_flag) { + hlw_cf1_voltage_pulse_length = hlw_cf1_pulse_length; + hlw_cf1_voltage_max_pulse_counter = hlw_cf1_pulse_counter; } else { - hlw_cf1i_plen = hlw_cf1_plen; - hlw_cf1i_pcntmax = hlw_cf1_pcnt; + hlw_cf1_current_pulse_length = hlw_cf1_pulse_length; + hlw_cf1_current_max_pulse_counter = hlw_cf1_pulse_counter; } - hlw_cf1_ptot = 0; - hlw_cf1_pcnt = 0; + hlw_cf1_summed_pulse_length = 0; + hlw_cf1_pulse_counter = 0; } } -void hlw_savestate() +void HlwSaveState() { - sysCfg.hlw_kWhdoy = (rtcTime.Valid) ? rtcTime.DayOfYear : 0; - sysCfg.hlw_kWhtoday = hlw_kWhtoday; - sysCfg.hlw_kWhtotal = rtcMem.hlw_kWhtotal; + Settings.hlw_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0; + Settings.hlw_kWhtoday = hlw_kWhtoday; + Settings.hlw_kWhtotal = RtcSettings.hlw_kWhtotal; } -void hlw_readEnergy(byte option, float &et, float &ed, float &e, float &w, float &u, float &i, float &c) +void HlwReadEnergy(byte option, float &total_energy, float &daily_energy, float &energy, float &watts, float &voltage, float ¤t, float &power_factor) { /* option 0 = do not calculate period energy usage * option 1 = calculate period energy usage @@ -192,91 +205,90 @@ void hlw_readEnergy(byte option, float &et, float &ed, float &e, float &w, float unsigned long hlw_u; unsigned long hlw_i; uint16_t hlw_period; - uint16_t hlw_interval; -//snprintf_P(log_data, sizeof(log_data), PSTR("HLW: CF %d, CF1U %d (%d), CF1I %d (%d)"), hlw_cf_plen, hlw_cf1u_plen, hlw_cf1u_pcntmax, hlw_cf1i_plen, hlw_cf1i_pcntmax); -//addLog(LOG_LEVEL_DEBUG); +//snprintf_P(log_data, sizeof(log_data), PSTR("HLW: CF %d, CF1U %d (%d), CF1I %d (%d)"), hlw_cf_pulse_length, hlw_cf1_voltage_pulse_length, hlw_cf1_voltage_max_pulse_counter, hlw_cf1_current_pulse_length, hlw_cf1_current_max_pulse_counter); +//AddLog(LOG_LEVEL_DEBUG); - et = (float)(rtcMem.hlw_kWhtotal + (cur_kWhtoday / 1000)) / 100000; - ed = 0; + total_energy = (float)(RtcSettings.hlw_kWhtotal + (cur_kWhtoday / 1000)) / 100000; + daily_energy = 0; if (cur_kWhtoday) { - ed = (float)cur_kWhtoday / 100000000; + daily_energy = (float)cur_kWhtoday / 100000000; } - e = 0; + energy = 0; if (option) { if (!hlw_lasttime) { - hlw_period = sysCfg.tele_period; + hlw_period = Settings.tele_period; } else { - hlw_period = rtc_loctime() - hlw_lasttime; + hlw_period = LocalTime() - hlw_lasttime; } - hlw_lasttime = rtc_loctime(); + hlw_lasttime = LocalTime(); if (hlw_period) { - hlw_interval = 3600 / hlw_period; - if (hlw_Ecntr) { - hlw_len = hlw_period * 1000000 / hlw_Ecntr; + uint16_t hlw_interval = 3600 / hlw_period; + if (hlw_energy_counter) { + hlw_len = hlw_period * 1000000 / hlw_energy_counter; if (hlw_interval && hlw_len) { - hlw_Ecntr = 0; - hlw_temp = ((HLW_PREF * sysCfg.hlw_pcal) / hlw_len) / hlw_interval; - e = (float)hlw_temp / 10; + hlw_energy_counter = 0; + hlw_temp = ((HLW_PREF * Settings.hlw_power_calibration) / hlw_len) / hlw_interval; + energy = (float)hlw_temp / 10; } } } } - w = 0; - if (hlw_cf_plen && (power &1) && !hlw_load_off) { - hlw_w = (HLW_PREF * sysCfg.hlw_pcal) / hlw_cf_plen; - w = (float)hlw_w / 10; + watts = 0; + if (hlw_cf_pulse_length && (power &1) && !hlw_load_off) { + hlw_w = (HLW_PREF * Settings.hlw_power_calibration) / hlw_cf_pulse_length; + watts = (float)hlw_w / 10; } - u = 0; - if (hlw_cf1u_plen && (power &1)) { // If powered on always provide voltage - hlw_u = (HLW_UREF * sysCfg.hlw_ucal) / hlw_cf1u_plen; - u = (float)hlw_u / 10; + voltage = 0; + if (hlw_cf1_voltage_pulse_length && (power &1)) { // If powered on always provide voltage + hlw_u = (HLW_UREF * Settings.hlw_voltage_calibration) / hlw_cf1_voltage_pulse_length; + voltage = (float)hlw_u / 10; } - i = 0; - if (hlw_cf1i_plen && w) { // No current if no power being consumed - hlw_i = (HLW_IREF * sysCfg.hlw_ical) / hlw_cf1i_plen; - i = (float)hlw_i / 1000; + current = 0; + if (hlw_cf1_current_pulse_length && watts) { // No current if no power being consumed + hlw_i = (HLW_IREF * Settings.hlw_current_calibration) / hlw_cf1_current_pulse_length; + current = (float)hlw_i / 1000; } - c = 0; - if (hlw_i && hlw_u && hlw_w && w) { + power_factor = 0; + if (hlw_i && hlw_u && hlw_w && watts) { hlw_temp = (hlw_w * 100) / ((hlw_u * hlw_i) / 1000); if (hlw_temp > 100) { hlw_temp = 100; } - c = (float)hlw_temp / 100; + power_factor = (float)hlw_temp / 100; } } -void hlw_init() +void HlwInit() { - if (!sysCfg.hlw_pcal || (4975 == sysCfg.hlw_pcal)) { - sysCfg.hlw_pcal = HLW_PREF_PULSE; - sysCfg.hlw_ucal = HLW_UREF_PULSE; - sysCfg.hlw_ical = HLW_IREF_PULSE; + if (!Settings.hlw_power_calibration || (4975 == Settings.hlw_power_calibration)) { + Settings.hlw_power_calibration = HLW_PREF_PULSE; + Settings.hlw_voltage_calibration = HLW_UREF_PULSE; + Settings.hlw_current_calibration = HLW_IREF_PULSE; } - hlw_cf_plen = 0; - hlw_cf_last = 0; - hlw_cf1_plen = 0; - hlw_cf1_last = 0; - hlw_cf1u_plen = 0; - hlw_cf1i_plen = 0; - hlw_cf1u_pcntmax = 0; - hlw_cf1i_pcntmax = 0; + hlw_cf_pulse_length = 0; + hlw_cf_pulse_last_time = 0; + hlw_cf1_pulse_length = 0; + hlw_cf1_pulse_last_time = 0; + hlw_cf1_voltage_pulse_length = 0; + hlw_cf1_current_pulse_length = 0; + hlw_cf1_voltage_max_pulse_counter = 0; + hlw_cf1_current_max_pulse_counter = 0; hlw_load_off = 1; - hlw_Ecntr = 0; - hlw_EDcntr = 0; - hlw_kWhtoday = (RTC_Valid()) ? rtcMem.hlw_kWhtoday : 0; + hlw_energy_counter = 0; + hlw_energy_period_counter = 0; + hlw_kWhtoday = (RtcSettingsValid()) ? RtcSettings.hlw_kWhtoday : 0; - hlw_SELflag = 0; // Voltage; + hlw_select_ui_flag = 0; // Voltage; pinMode(pin[GPIO_HLW_SEL], OUTPUT); - digitalWrite(pin[GPIO_HLW_SEL], hlw_SELflag); + digitalWrite(pin[GPIO_HLW_SEL], hlw_select_ui_flag); pinMode(pin[GPIO_HLW_CF1], INPUT_PULLUP); - attachInterrupt(pin[GPIO_HLW_CF1], hlw_cf1_interrupt, FALLING); + attachInterrupt(pin[GPIO_HLW_CF1], HlwCf1Interrupt, FALLING); pinMode(pin[GPIO_HLW_CF], INPUT_PULLUP); - attachInterrupt(pin[GPIO_HLW_CF], hlw_cf_interrupt, FALLING); + attachInterrupt(pin[GPIO_HLW_CF], HlwCfInterrupt, FALLING); hlw_startup = 1; hlw_lasttime = 0; @@ -287,41 +299,41 @@ void hlw_init() /********************************************************************************************/ -boolean hlw_margin(byte type, uint16_t margin, uint16_t value, byte &flag, byte &saveflag) +boolean HlwMargin(byte type, uint16_t margin, uint16_t value, byte &flag, byte &save_flag) { byte change; if (!margin) { return false; } - change = saveflag; + change = save_flag; if (type) { flag = (value > margin); } else { flag = (value < margin); } - saveflag = flag; - return (change != saveflag); + save_flag = flag; + return (change != save_flag); } -void hlw_setPowerSteadyCounter(byte value) +void HlwSetPowerSteadyCounter(byte value) { power_steady_cntr = 2; } -void hlw_margin_chk() +void HlwMarginCheck() { - float pet; - float ped; - float pe; - float pw; - float pu; - float pi; - float pc; - uint16_t uped; - uint16_t pwv; - uint16_t puv; - uint16_t piv; + float total_energy; + float daily_energy; + float energy; + float watts; + float voltage; + float current; + float power_factor; + uint16_t udaily_energy; + uint16_t uwatts; + uint16_t uvoltage; + uint16_t ucurrent; boolean flag; boolean jsonflg; @@ -330,69 +342,69 @@ void hlw_margin_chk() return; } - hlw_readEnergy(0, pet, ped, pe, pw, pu, pi, pc); - if (power && (sysCfg.hlw_pmin || sysCfg.hlw_pmax || sysCfg.hlw_umin || sysCfg.hlw_umax || sysCfg.hlw_imin || sysCfg.hlw_imax)) { - pwv = (uint16_t)(pw); - puv = (uint16_t)(pu); - piv = (uint16_t)(pi * 1000); + HlwReadEnergy(0, total_energy, daily_energy, energy, watts, voltage, current, power_factor); + if (power && (Settings.hlw_pmin || Settings.hlw_pmax || Settings.hlw_umin || Settings.hlw_umax || Settings.hlw_imin || Settings.hlw_imax)) { + uwatts = (uint16_t)(watts); + uvoltage = (uint16_t)(voltage); + ucurrent = (uint16_t)(current * 1000); -// snprintf_P(log_data, sizeof(log_data), PSTR("HLW: W %d, U %d, I %d"), pw, pu, piv); -// addLog(LOG_LEVEL_DEBUG); +// snprintf_P(log_data, sizeof(log_data), PSTR("HLW: W %d, U %d, I %d"), watts, voltage, ucurrent); +// AddLog(LOG_LEVEL_DEBUG); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); jsonflg = 0; - if (hlw_margin(0, sysCfg.hlw_pmin, pwv, flag, hlw_pminflg)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_POWERLOW "\":\"%s\""), mqtt_data, (jsonflg)?", ":"", getStateText(flag)); + if (HlwMargin(0, Settings.hlw_pmin, uwatts, flag, hlw_pmin_flag)) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_POWERLOW "\":\"%s\""), mqtt_data, (jsonflg)?", ":"", GetStateText(flag)); jsonflg = 1; } - if (hlw_margin(1, sysCfg.hlw_pmax, pwv, flag, hlw_pmaxflg)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_POWERHIGH "\":\"%s\""), mqtt_data, (jsonflg)?", ":"", getStateText(flag)); + if (HlwMargin(1, Settings.hlw_pmax, uwatts, flag, hlw_pmax_flag)) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_POWERHIGH "\":\"%s\""), mqtt_data, (jsonflg)?", ":"", GetStateText(flag)); jsonflg = 1; } - if (hlw_margin(0, sysCfg.hlw_umin, puv, flag, hlw_uminflg)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_VOLTAGELOW "\":\"%s\""), mqtt_data, (jsonflg)?", ":"", getStateText(flag)); + if (HlwMargin(0, Settings.hlw_umin, uvoltage, flag, hlw_umin_flag)) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_VOLTAGELOW "\":\"%s\""), mqtt_data, (jsonflg)?", ":"", GetStateText(flag)); jsonflg = 1; } - if (hlw_margin(1, sysCfg.hlw_umax, puv, flag, hlw_umaxflg)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_VOLTAGEHIGH "\":\"%s\""), mqtt_data, (jsonflg)?", ":"", getStateText(flag)); + if (HlwMargin(1, Settings.hlw_umax, uvoltage, flag, hlw_umax_flag)) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_VOLTAGEHIGH "\":\"%s\""), mqtt_data, (jsonflg)?", ":"", GetStateText(flag)); jsonflg = 1; } - if (hlw_margin(0, sysCfg.hlw_imin, piv, flag, hlw_iminflg)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_CURRENTLOW "\":\"%s\""), mqtt_data, (jsonflg)?", ":"", getStateText(flag)); + if (HlwMargin(0, Settings.hlw_imin, ucurrent, flag, hlw_imin_flag)) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_CURRENTLOW "\":\"%s\""), mqtt_data, (jsonflg)?", ":"", GetStateText(flag)); jsonflg = 1; } - if (hlw_margin(1, sysCfg.hlw_imax, piv, flag, hlw_imaxflg)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_CURRENTHIGH "\":\"%s\""), mqtt_data, (jsonflg)?", ":"", getStateText(flag)); + if (HlwMargin(1, Settings.hlw_imax, ucurrent, flag, hlw_imax_flag)) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_CURRENTHIGH "\":\"%s\""), mqtt_data, (jsonflg)?", ":"", GetStateText(flag)); jsonflg = 1; } if (jsonflg) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); - mqtt_publish_topic_P(2, PSTR(D_RSLT_MARGINS)); - hlw_mqttPresent(0); + MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_MARGINS)); + MqttShowHlw8012(0); } } #if FEATURE_POWER_LIMIT // Max Power - if (sysCfg.hlw_mpl) { - if (pw > sysCfg.hlw_mpl) { + if (Settings.hlw_mpl) { + if (watts > Settings.hlw_mpl) { if (!hlw_mplh_counter) { - hlw_mplh_counter = sysCfg.hlw_mplh; + hlw_mplh_counter = Settings.hlw_mplh; } else { hlw_mplh_counter--; if (!hlw_mplh_counter) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_MAXPOWERREACHED "\":\"%d%s\"}"), pwv, (sysCfg.flag.value_units) ? " " D_UNIT_WATT : ""); - mqtt_publish_topic_P(1, S_RSLT_WARNING); - hlw_mqttPresent(0); - do_cmnd_power(1, 0); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_MAXPOWERREACHED "\":\"%d%s\"}"), uwatts, (Settings.flag.value_units) ? " " D_UNIT_WATT : ""); + MqttPublishPrefixTopic_P(1, S_RSLT_WARNING); + MqttShowHlw8012(0); + ExecuteCommandPower(1, 0); if (!hlw_mplr_counter) { - hlw_mplr_counter = sysCfg.param[P_MAX_POWER_RETRY] +1; + hlw_mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1; } - hlw_mplw_counter = sysCfg.hlw_mplw; + hlw_mplw_counter = Settings.hlw_mplw; } } } - else if (power && (pwv <= sysCfg.hlw_mpl)) { + else if (power && (uwatts <= Settings.hlw_mpl)) { hlw_mplh_counter = 0; hlw_mplr_counter = 0; hlw_mplw_counter = 0; @@ -404,13 +416,13 @@ void hlw_margin_chk() if (hlw_mplr_counter) { hlw_mplr_counter--; if (hlw_mplr_counter) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_POWERMONITOR "\":\"%s\"}"), getStateText(1)); - mqtt_publish_topic_P(5, PSTR(D_POWERMONITOR)); - do_cmnd_power(1, 1); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); + MqttPublishPrefixTopic_P(5, PSTR(D_POWERMONITOR)); + ExecuteCommandPower(1, 1); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_MAXPOWERREACHEDRETRY "\":\"%s\"}"), getStateText(0)); - mqtt_publish_topic_P(1, S_RSLT_WARNING); - hlw_mqttPresent(0); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); + MqttPublishPrefixTopic_P(1, S_RSLT_WARNING); + MqttShowHlw8012(0); } } } @@ -418,21 +430,21 @@ void hlw_margin_chk() } // Max Energy - if (sysCfg.hlw_mkwh) { - uped = (uint16_t)(ped * 1000); - if (!hlw_mkwh_state && (rtcTime.Hour == sysCfg.hlw_mkwhs)) { + if (Settings.hlw_mkwh) { + udaily_energy = (uint16_t)(daily_energy * 1000); + if (!hlw_mkwh_state && (RtcTime.hour == Settings.hlw_mkwhs)) { hlw_mkwh_state = 1; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_ENERGYMONITOR "\":\"%s\"}"), getStateText(1)); - mqtt_publish_topic_P(5, PSTR(D_ENERGYMONITOR)); - do_cmnd_power(1, 1); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); + MqttPublishPrefixTopic_P(5, PSTR(D_ENERGYMONITOR)); + ExecuteCommandPower(1, 1); } - else if ((1 == hlw_mkwh_state) && (uped >= sysCfg.hlw_mkwh)) { + else if ((1 == hlw_mkwh_state) && (udaily_energy >= Settings.hlw_mkwh)) { hlw_mkwh_state = 2; - dtostrfd(ped, 3, mqtt_data); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (sysCfg.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : ""); - mqtt_publish_topic_P(1, S_RSLT_WARNING); - hlw_mqttPresent(0); - do_cmnd_power(1, 0); + dtostrfd(daily_energy, 3, mqtt_data); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : ""); + MqttPublishPrefixTopic_P(1, S_RSLT_WARNING); + MqttShowHlw8012(0); + ExecuteCommandPower(1, 0); } } #endif // FEATURE_POWER_LIMIT @@ -442,172 +454,198 @@ void hlw_margin_chk() * Commands \*********************************************************************************************/ -boolean hlw_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload) +boolean HlwCommand(char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload) { + char command [CMDSZ]; + char sunit[CMDSZ]; boolean serviced = true; - uint8_t caltext = 0; + uint8_t status_flag = 0; + uint8_t unit = 0; + unsigned long nvalue = 0; - if (!strcasecmp_P(type, PSTR(D_CMND_POWERLOW))) { + int command_code = GetCommandCode(command, sizeof(command), type, kHlw8012Commands); + if (CMND_POWERLOW == command_code) { if ((payload >= 0) && (payload < 3601)) { - sysCfg.hlw_pmin = payload; + Settings.hlw_pmin = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_POWERLOW "\":\"%d%s\"}"), sysCfg.hlw_pmin, (sysCfg.flag.value_units) ? " " D_UNIT_WATT : ""); + nvalue = Settings.hlw_pmin; + unit = UNIT_WATT; } - else if (!strcasecmp_P(type, PSTR(D_CMND_POWERHIGH))) { + else if (CMND_POWERHIGH == command_code) { if ((payload >= 0) && (payload < 3601)) { - sysCfg.hlw_pmax = payload; + Settings.hlw_pmax = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_POWERHIGH "\":\"%d%s\"}"), sysCfg.hlw_pmax, (sysCfg.flag.value_units) ? " " D_UNIT_WATT : ""); + nvalue = Settings.hlw_pmax; + unit = UNIT_WATT; } - else if (!strcasecmp_P(type, PSTR(D_CMND_VOLTAGELOW))) { + else if (CMND_VOLTAGELOW == command_code) { if ((payload >= 0) && (payload < 501)) { - sysCfg.hlw_umin = payload; + Settings.hlw_umin = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_VOLTAGELOW "\":\"%d%s\"}"), sysCfg.hlw_umin, (sysCfg.flag.value_units) ? " " D_UNIT_VOLT : ""); + nvalue = Settings.hlw_umin; + unit = UNIT_VOLT; } - else if (!strcasecmp_P(type, PSTR(D_CMND_VOLTAGEHIGH))) { + else if (CMND_VOLTAGEHIGH == command_code) { if ((payload >= 0) && (payload < 501)) { - sysCfg.hlw_umax = payload; + Settings.hlw_umax = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_VOLTAGEHIGH "\":\"%d%s\"}"), sysCfg.hlw_umax, (sysCfg.flag.value_units) ? " " D_UNIT_VOLT : ""); + nvalue = Settings.hlw_umax; + unit = UNIT_VOLT; } - else if (!strcasecmp_P(type, PSTR(D_CMND_CURRENTLOW))) { + else if (CMND_CURRENTLOW == command_code) { if ((payload >= 0) && (payload < 16001)) { - sysCfg.hlw_imin = payload; + Settings.hlw_imin = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_CURRENTLOW "\":\"%d%s\"}"), sysCfg.hlw_imin, (sysCfg.flag.value_units) ? " " D_UNIT_MILLIAMPERE : ""); + nvalue = Settings.hlw_imin; + unit = UNIT_MILLIAMPERE; } - else if (!strcasecmp_P(type, PSTR(D_CMND_CURRENTHIGH))) { + else if (CMND_CURRENTHIGH == command_code) { if ((payload >= 0) && (payload < 16001)) { - sysCfg.hlw_imax = payload; + Settings.hlw_imax = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_CURRENTHIGH "\":\"%d%s\"}"), sysCfg.hlw_imax, (sysCfg.flag.value_units) ? " " D_UNIT_MILLIAMPERE : ""); + nvalue = Settings.hlw_imax; + unit = UNIT_MILLIAMPERE; } - else if (!strcasecmp_P(type, PSTR(D_CMND_ENERGYRESET))) { + else if (CMND_ENERGYRESET == command_code) { if ((payload >= 1) && (payload <= 3)) { switch (payload) { case 1: hlw_kWhtoday = 0; - rtcMem.hlw_kWhtoday = 0; - sysCfg.hlw_kWhtoday = 0; + RtcSettings.hlw_kWhtoday = 0; + Settings.hlw_kWhtoday = 0; break; case 2: - sysCfg.hlw_kWhyesterday = 0; + Settings.hlw_kWhyesterday = 0; break; case 3: - rtcMem.hlw_kWhtotal = 0; - sysCfg.hlw_kWhtotal = rtcMem.hlw_kWhtotal; + RtcSettings.hlw_kWhtotal = 0; + Settings.hlw_kWhtotal = RtcSettings.hlw_kWhtotal; break; } } - char sey[10]; - char sen[10]; - char set[10]; - dtostrfd((float)sysCfg.hlw_kWhyesterday / 100000000, sysCfg.flag.energy_resolution, sey); - dtostrfd((float)rtcMem.hlw_kWhtoday / 100000000, sysCfg.flag.energy_resolution, sen); - dtostrfd((float)(rtcMem.hlw_kWhtotal + (hlw_kWhtoday / 1000)) / 100000, sysCfg.flag.energy_resolution, set); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_ENERGYRESET "\":{\"" D_TOTAL "\":%s, \"" D_YESTERDAY "\":%s, \"" D_TODAY "\":%s}}"), set, sey, sen); + char syesterday_energy[10]; + char stoday_energy[10]; + char stotal_energy[10]; + dtostrfd((float)Settings.hlw_kWhyesterday / 100000000, Settings.flag.energy_resolution, syesterday_energy); + dtostrfd((float)RtcSettings.hlw_kWhtoday / 100000000, Settings.flag.energy_resolution, stoday_energy); + dtostrfd((float)(RtcSettings.hlw_kWhtotal + (hlw_kWhtoday / 1000)) / 100000, Settings.flag.energy_resolution, stotal_energy); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"" D_TOTAL "\":%s, \"" D_YESTERDAY "\":%s, \"" D_TODAY "\":%s}}"), + command, stotal_energy, syesterday_energy, stoday_energy); + status_flag = 1; } - else if (!strcasecmp_P(type, PSTR(D_CMND_HLWPCAL))) { + else if (CMND_HLWPCAL == command_code) { if ((payload > 0) && (payload < 32001)) { - sysCfg.hlw_pcal = (payload > 4000) ? payload : HLW_PREF_PULSE; // 12530 + Settings.hlw_power_calibration = (payload > 4000) ? payload : HLW_PREF_PULSE; // 12530 } - caltext = 1; + nvalue = Settings.hlw_power_calibration; + unit = UNIT_MICROSECOND; } - else if (!strcasecmp_P(type, PSTR(D_CMND_HLWPSET))) { - if ((payload > 0) && (payload < 3601) && hlw_cf_plen) { - sysCfg.hlw_pcal = (payload * 10 * hlw_cf_plen) / HLW_PREF; + else if (CMND_HLWPSET == command_code) { + if ((payload > 0) && (payload < 3601) && hlw_cf_pulse_length) { + Settings.hlw_power_calibration = (payload * 10 * hlw_cf_pulse_length) / HLW_PREF; } - caltext = 1; + snprintf_P(command, sizeof(command), PSTR(D_CMND_HLWPCAL)); + nvalue = Settings.hlw_power_calibration; + unit = UNIT_MICROSECOND; } - else if (!strcasecmp_P(type, PSTR(D_CMND_HLWUCAL))) { + else if (CMND_HLWUCAL == command_code) { if ((payload > 0) && (payload < 32001)) { - sysCfg.hlw_ucal = (payload > 999) ? payload : HLW_UREF_PULSE; // 1950 + Settings.hlw_voltage_calibration = (payload > 999) ? payload : HLW_UREF_PULSE; // 1950 } - caltext = 2; + nvalue = Settings.hlw_voltage_calibration; + unit = UNIT_MICROSECOND; } - else if (!strcasecmp_P(type, PSTR(D_CMND_HLWUSET))) { - if ((payload > 0) && (payload < 501) && hlw_cf1u_plen) { - sysCfg.hlw_ucal = (payload * 10 * hlw_cf1u_plen) / HLW_UREF; + else if (CMND_HLWUSET == command_code) { + if ((payload > 0) && (payload < 501) && hlw_cf1_voltage_pulse_length) { + Settings.hlw_voltage_calibration = (payload * 10 * hlw_cf1_voltage_pulse_length) / HLW_UREF; } - caltext = 2; + snprintf_P(command, sizeof(command), PSTR(D_CMND_HLWUCAL)); + nvalue = Settings.hlw_voltage_calibration; + unit = UNIT_MICROSECOND; } - else if (!strcasecmp_P(type, PSTR(D_CMND_HLWICAL))) { + else if (CMND_HLWICAL == command_code) { if ((payload > 0) && (payload < 32001)) { - sysCfg.hlw_ical = (payload > 1100) ? payload : HLW_IREF_PULSE; // 3500 + Settings.hlw_current_calibration = (payload > 1100) ? payload : HLW_IREF_PULSE; // 3500 } - caltext = 3; + nvalue = Settings.hlw_current_calibration; + unit = UNIT_MICROSECOND; } - else if (!strcasecmp_P(type, PSTR(D_CMND_HLWISET))) { - if ((payload > 0) && (payload < 16001) && hlw_cf1i_plen) { - sysCfg.hlw_ical = (payload * hlw_cf1i_plen) / HLW_IREF; + else if (CMND_HLWISET == command_code) { + if ((payload > 0) && (payload < 16001) && hlw_cf1_current_pulse_length) { + Settings.hlw_current_calibration = (payload * hlw_cf1_current_pulse_length) / HLW_IREF; } - caltext = 3; + snprintf_P(command, sizeof(command), PSTR(D_CMND_HLWPCAL)); + nvalue = Settings.hlw_current_calibration; + unit = UNIT_MICROSECOND; } #if FEATURE_POWER_LIMIT - else if (!strcasecmp_P(type, PSTR(D_CMND_MAXPOWER))) { + else if (CMND_MAXPOWER == command_code) { if ((payload >= 0) && (payload < 3601)) { - sysCfg.hlw_mpl = payload; + Settings.hlw_mpl = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MAXPOWER "\":\"%d%s\"}"), sysCfg.hlw_mpl, (sysCfg.flag.value_units) ? " " D_UNIT_WATT : ""); + nvalue = Settings.hlw_mpl; + unit = UNIT_WATT; } - else if (!strcasecmp_P(type, PSTR(D_CMND_MAXPOWERHOLD))) { + else if (CMND_MAXPOWERHOLD == command_code) { if ((payload >= 0) && (payload < 3601)) { - sysCfg.hlw_mplh = (1 == payload) ? MAX_POWER_HOLD : payload; + Settings.hlw_mplh = (1 == payload) ? MAX_POWER_HOLD : payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MAXPOWERHOLD "\":\"%d%s\"}"), sysCfg.hlw_mplh, (sysCfg.flag.value_units) ? " " D_UNIT_SECOND : ""); + nvalue = Settings.hlw_mplh; + unit = UNIT_SECOND; } - else if (!strcasecmp_P(type, PSTR(D_CMND_MAXPOWERWINDOW))) { + else if (CMND_MAXPOWERWINDOW == command_code) { if ((payload >= 0) && (payload < 3601)) { - sysCfg.hlw_mplw = (1 == payload) ? MAX_POWER_WINDOW : payload; + Settings.hlw_mplw = (1 == payload) ? MAX_POWER_WINDOW : payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MAXPOWERWINDOW "\":\"%d%s\"}"), sysCfg.hlw_mplw, (sysCfg.flag.value_units) ? " " D_UNIT_SECOND : ""); + nvalue = Settings.hlw_mplw; + unit = UNIT_SECOND; } - else if (!strcasecmp_P(type, PSTR(D_CMND_SAFEPOWER))) { + else if (CMND_SAFEPOWER == command_code) { if ((payload >= 0) && (payload < 3601)) { - sysCfg.hlw_mspl = payload; + Settings.hlw_mspl = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_SAFEPOWER "\":\"%d%s\"}"), sysCfg.hlw_mspl, (sysCfg.flag.value_units) ? " " D_UNIT_WATT : ""); + nvalue = Settings.hlw_mspl; + unit = UNIT_WATT; } - else if (!strcasecmp_P(type, PSTR(D_CMND_SAFEPOWERHOLD))) { + else if (CMND_SAFEPOWERHOLD == command_code) { if ((payload >= 0) && (payload < 3601)) { - sysCfg.hlw_msplh = (1 == payload) ? SAFE_POWER_HOLD : payload; + Settings.hlw_msplh = (1 == payload) ? SAFE_POWER_HOLD : payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_SAFEPOWERHOLD "\":\"%d%s\"}"), sysCfg.hlw_msplh, (sysCfg.flag.value_units) ? " " D_UNIT_SECOND : ""); + nvalue = Settings.hlw_msplh; + unit = UNIT_SECOND; } - else if (!strcasecmp_P(type, PSTR(D_CMND_SAFEPOWERWINDOW))) { + else if (CMND_SAFEPOWERWINDOW == command_code) { if ((payload >= 0) && (payload < 1440)) { - sysCfg.hlw_msplw = (1 == payload) ? SAFE_POWER_WINDOW : payload; + Settings.hlw_msplw = (1 == payload) ? SAFE_POWER_WINDOW : payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_SAFEPOWERWINDOW "\":\"%d%s\"}"), sysCfg.hlw_msplw, (sysCfg.flag.value_units) ? " " D_UNIT_MINUTE : ""); + nvalue = Settings.hlw_msplw; + unit = UNIT_MINUTE; } - else if (!strcasecmp_P(type, PSTR(D_CMND_MAXENERGY))) { + else if (CMND_MAXENERGY == command_code) { if ((payload >= 0) && (payload < 3601)) { - sysCfg.hlw_mkwh = payload; + Settings.hlw_mkwh = payload; hlw_mkwh_state = 3; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MAXENERGY "\":\"%d%s\"}"), sysCfg.hlw_mkwh, (sysCfg.flag.value_units) ? " " D_UNIT_WATTHOUR : ""); + nvalue = Settings.hlw_mkwh; + unit = UNIT_WATTHOUR; } - else if (!strcasecmp_P(type, PSTR(D_CMND_MAXENERGYSTART))) { + else if (CMND_MAXENERGYSTART == command_code) { if ((payload >= 0) && (payload < 24)) { - sysCfg.hlw_mkwhs = payload; + Settings.hlw_mkwhs = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MAXENERGYSTART "\":\"%d%s\"}"), sysCfg.hlw_mkwhs, (sysCfg.flag.value_units) ? " " D_UNIT_HOUR : ""); + nvalue = Settings.hlw_mkwhs; + unit = UNIT_HOUR; } #endif // FEATURE_POWER_LIMIT else { serviced = false; } - switch (caltext) { - case 1: - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_HLWPCAL "\":\"%d%s\"}"), sysCfg.hlw_pcal, (sysCfg.flag.value_units) ? " " D_UNIT_MICROSECOND : ""); - break; - case 2: - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_HLWUCAL "\":\"%d%s\"}"), sysCfg.hlw_ucal, (sysCfg.flag.value_units) ? " " D_UNIT_MICROSECOND : ""); - break; - case 3: - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_HLWICAL "\":\"%d%s\"}"), sysCfg.hlw_ical, (sysCfg.flag.value_units) ? " " D_UNIT_MICROSECOND : ""); - break; + if (!status_flag) { + if (Settings.flag.value_units) { + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SPACE_UNIT, command, nvalue, GetTextIndexed(sunit, sizeof(sunit), unit, kUnitNames)); + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, nvalue); + } } return serviced; } @@ -616,63 +654,65 @@ boolean hlw_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len * Presentation \*********************************************************************************************/ -void hlw_mqttStat(byte option) +void HlwMqttStat(byte option) { /* option 0 = do not show period energy usage * option 1 = show period energy usage */ - float pet; - float ped; - float pe; - float pw; - float pu; - float pi; - float pc; - char spet[10]; - char sped[10]; - char spe[10]; - char spw[10]; - char spu[10]; - char spi[10]; - char spc[10]; - char sey[10]; + float total_energy; + float daily_energy; + float energy; + float watts; + float voltage; + float current; + float power_factor; + char stotal_energy[10]; + char sdaily_energy[10]; + char senergy[10]; + char swatts[10]; + char svoltage[10]; + char scurrent[10]; + char spower_factor[10]; + char syesterday_energy[10]; char speriod[20]; - hlw_readEnergy(option, pet, ped, pe, pw, pu, pi, pc); - dtostrfd(pet, sysCfg.flag.energy_resolution, spet); - dtostrfd(ped, sysCfg.flag.energy_resolution, sped); - dtostrfd(pe, sysCfg.flag.wattage_resolution, spe); - dtostrfd(pw, sysCfg.flag.wattage_resolution, spw); - dtostrfd(pu, sysCfg.flag.voltage_resolution, spu); - dtostrfd(pi, 3, spi); - dtostrfd(pc, 2, spc); - dtostrfd((float)sysCfg.hlw_kWhyesterday / 100000000, sysCfg.flag.energy_resolution, sey); - snprintf_P(speriod, sizeof(speriod), PSTR(", \"" D_PERIOD "\":%s"), spe); + HlwReadEnergy(option, total_energy, daily_energy, energy, watts, voltage, current, power_factor); + dtostrfd(total_energy, Settings.flag.energy_resolution, stotal_energy); + dtostrfd(daily_energy, Settings.flag.energy_resolution, sdaily_energy); + dtostrfd(energy, Settings.flag.wattage_resolution, senergy); + dtostrfd(watts, Settings.flag.wattage_resolution, swatts); + dtostrfd(voltage, Settings.flag.voltage_resolution, svoltage); + dtostrfd(current, 3, scurrent); + dtostrfd(power_factor, 2, spower_factor); + dtostrfd((float)Settings.hlw_kWhyesterday / 100000000, Settings.flag.energy_resolution, syesterday_energy); + snprintf_P(speriod, sizeof(speriod), PSTR(", \"" D_PERIOD "\":%s"), senergy); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_TOTAL "\":%s, \"" D_YESTERDAY "\":%s, \"" D_TODAY "\":%s%s, \"" D_POWERUSAGE "\":%s, \"" D_POWERFACTOR "\":%s, \"" D_VOLTAGE "\":%s, \"" D_CURRENT "\":%s}"), - mqtt_data, spet, sey, sped, (option) ? speriod : "", spw, spc, spu, spi); + mqtt_data, stotal_energy, syesterday_energy, sdaily_energy, (option) ? speriod : "", swatts, spower_factor, svoltage, scurrent); #ifdef USE_DOMOTICZ if (option) { // Only send if telemetry - dtostrfd(pet * 1000, 1, spet); - domoticz_sensor4((uint16_t)pw, spet); + dtostrfd(total_energy * 1000, 1, stotal_energy); + DomoticzSensorPowerEnergy((uint16_t)watts, stotal_energy); // PowerUsage, EnergyToday + DomoticzSensor(DZ_VOLTAGE, svoltage); // Voltage + DomoticzSensor(DZ_CURRENT, scurrent); // Current } #endif // USE_DOMOTICZ } -void hlw_mqttPresent(byte option) +void MqttShowHlw8012(byte option) { /* option 0 = do not show period energy usage * option 1 = show period energy usage */ // {"Time":"2017-03-04T13:37:24", "Total":0.013, "Yesterday":0.013, "Today":0.000, "Period":0, "Power":0, "Factor":0.00, "Voltage":0, "Current":0.000} - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_TIME "\":\"%s\", "), getDateTime().c_str()); - hlw_mqttStat(option); - mqtt_publish_topic_P(2, PSTR(D_RSLT_ENERGY)); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_TIME "\":\"%s\", "), GetDateAndTime().c_str()); + HlwMqttStat(option); + MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_ENERGY), Settings.flag.mqtt_sensor_retain); } -void hlw_mqttStatus() +void HlwMqttStatus() { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS8_POWER "\":{")); - hlw_mqttStat(0); + HlwMqttStat(0); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } @@ -686,34 +726,33 @@ const char HTTP_ENERGY_SNS[] PROGMEM = "" D_ENERGY_YESTERDAY "%s " D_UNIT_KILOWATTHOUR "" "" D_ENERGY_TOTAL "%s " D_UNIT_KILOWATTHOUR ""; -String hlw_webPresent() +String WebShowHlw() { - float pet; - float ped; - float pe; - float pw; - float pu; - float pi; - float pc; - char spet[10]; - char sped[10]; - char spw[10]; - char spu[10]; - char spi[10]; - char spc[10]; - char sey[10]; + float total_energy; + float daily_energy; + float energy; + float watts; + float voltage; + float current; + float power_factor; + char stotal_energy[10]; + char sdaily_energy[10]; + char swatts[10]; + char svoltage[10]; + char scurrent[10]; + char spower_factor[10]; + char syesterday_energy[10]; char sensor[400]; - hlw_readEnergy(0, pet, ped, pe, pw, pu, pi, pc); - dtostrfi(pet, sysCfg.flag.energy_resolution, spet); - dtostrfi(ped, sysCfg.flag.energy_resolution, sped); - dtostrfi(pw, sysCfg.flag.wattage_resolution, spw); - dtostrfi(pu, sysCfg.flag.voltage_resolution, spu); - dtostrfi(pi, 3, spi); - dtostrfi(pc, 2, spc); - dtostrfi((float)sysCfg.hlw_kWhyesterday / 100000000, sysCfg.flag.energy_resolution, sey); - snprintf_P(sensor, sizeof(sensor), HTTP_ENERGY_SNS, spu, spi, spw, spc, sped, sey, spet); + HlwReadEnergy(0, total_energy, daily_energy, energy, watts, voltage, current, power_factor); + dtostrfi(total_energy, Settings.flag.energy_resolution, stotal_energy); + dtostrfi(daily_energy, Settings.flag.energy_resolution, sdaily_energy); + dtostrfi(watts, Settings.flag.wattage_resolution, swatts); + dtostrfi(voltage, Settings.flag.voltage_resolution, svoltage); + dtostrfi(current, 3, scurrent); + dtostrfi(power_factor, 2, spower_factor); + dtostrfi((float)Settings.hlw_kWhyesterday / 100000000, Settings.flag.energy_resolution, syesterday_energy); + snprintf_P(sensor, sizeof(sensor), HTTP_ENERGY_SNS, svoltage, scurrent, swatts, spower_factor, sdaily_energy, syesterday_energy, stotal_energy); return String(sensor); } #endif // USE_WEBSERVER - diff --git a/sonoff/xsns_htu21.ino b/sonoff/xsns_htu21.ino index 658e03458..5bffbab52 100644 --- a/sonoff/xsns_htu21.ino +++ b/sonoff/xsns_htu21.ino @@ -52,13 +52,13 @@ #define HTU21_CRC8_POLYNOM 0x13100 -uint8_t htuaddr; -uint8_t htutype = 0; -uint8_t delayT; -uint8_t delayH = 50; -char htustype[7]; +uint8_t htu_address; +uint8_t htu_type = 0; +uint8_t delay_temp; +uint8_t delay_humidity = 50; +char htu_types[7]; -uint8_t check_crc8(uint16_t data) +uint8_t HtuCheckCrc8(uint16_t data) { for (uint8_t bit = 0; bit < 16; bit++) { if (data & 0x8000) { @@ -70,7 +70,7 @@ uint8_t check_crc8(uint16_t data) return data >>= 8; } -uint8_t htu21_readDeviceID(void) +uint8_t HtuReadDeviceId(void) { uint16_t deviceID = 0; uint8_t checksum = 0; @@ -84,7 +84,7 @@ uint8_t htu21_readDeviceID(void) deviceID = Wire.read() << 8; deviceID |= Wire.read(); checksum = Wire.read(); - if (check_crc8(deviceID) == checksum) { + if (HtuCheckCrc8(deviceID) == checksum) { deviceID = deviceID >> 8; } else { deviceID = 0; @@ -92,15 +92,15 @@ uint8_t htu21_readDeviceID(void) return (uint8_t)deviceID; } -void htu21_setRes(uint8_t resolution) +void HtuSetResolution(uint8_t resolution) { - uint8_t current = i2c_read8(HTU21_ADDR, HTU21_READREG); + uint8_t current = I2cRead8(HTU21_ADDR, HTU21_READREG); current &= 0x7E; // Replace current resolution bits with 0 current |= resolution; // Add new resolution bits to register - i2c_write8(HTU21_ADDR, HTU21_WRITEREG, current); + I2cWrite8(HTU21_ADDR, HTU21_WRITEREG, current); } -void htu21_reset(void) +void HtuReset(void) { Wire.beginTransmission(HTU21_ADDR); Wire.write(HTU21_RESET); @@ -108,9 +108,9 @@ void htu21_reset(void) delay(15); // Reset takes 15ms } -void htu21_heater(uint8_t heater) +void HtuHeater(uint8_t heater) { - uint8_t current = i2c_read8(HTU21_ADDR, HTU21_READREG); + uint8_t current = I2cRead8(HTU21_ADDR, HTU21_READREG); switch(heater) { @@ -121,18 +121,18 @@ void htu21_heater(uint8_t heater) default : current &= heater; break; } - i2c_write8(HTU21_ADDR, HTU21_WRITEREG, current); + I2cWrite8(HTU21_ADDR, HTU21_WRITEREG, current); } -boolean htu21_init() +boolean HtuInit() { - htu21_reset(); - htu21_heater(HTU21_HEATER_OFF); - htu21_setRes(HTU21_RES_RH12_T14); + HtuReset(); + HtuHeater(HTU21_HEATER_OFF); + HtuSetResolution(HTU21_RES_RH12_T14); return true; } -float htu21_readHumidity(void) +float HtuReadHumidity(void) { uint8_t checksum = 0; uint16_t sensorval = 0; @@ -143,7 +143,7 @@ float htu21_readHumidity(void) if (Wire.endTransmission() != 0) { return 0.0; // In case of error } - delay(delayH); // Sensor time at max resolution + delay(delay_humidity); // Sensor time at max resolution Wire.requestFrom(HTU21_ADDR, 3); if (3 <= Wire.available()) { @@ -151,7 +151,7 @@ float htu21_readHumidity(void) sensorval |= Wire.read(); // LSB checksum = Wire.read(); } - if (check_crc8(sensorval) != checksum) { + if (HtuCheckCrc8(sensorval) != checksum) { return 0.0; // Checksum mismatch } @@ -168,7 +168,7 @@ float htu21_readHumidity(void) return humidity; } -float htu21_readTemperature() +float HtuReadTemperature() { uint8_t checksum=0; uint16_t sensorval=0; @@ -179,7 +179,7 @@ float htu21_readTemperature() if (Wire.endTransmission() != 0) { return 0.0; // In case of error } - delay(delayT); // Sensor time at max resolution + delay(delay_temp); // Sensor time at max resolution Wire.requestFrom(HTU21_ADDR, 3); if (3 == Wire.available()) { @@ -187,15 +187,15 @@ float htu21_readTemperature() sensorval |= Wire.read(); // LSB checksum = Wire.read(); } - if (check_crc8(sensorval) != checksum) { + if (HtuCheckCrc8(sensorval) != checksum) { return 0.0; // Checksum mismatch } - t = convertTemp(0.002681 * (float)sensorval - 46.85); + t = ConvertTemp(0.002681 * (float)sensorval - 46.85); return t; } -float htu21_compensatedHumidity(float humidity, float temperature) +float HtuCompensatedHumidity(float humidity, float temperature) { if(humidity == 0.00 && temperature == 0.00) { return 0.0; @@ -205,48 +205,48 @@ float htu21_compensatedHumidity(float humidity, float temperature) } } -uint8_t htu_detect() +uint8_t HtuDetect() { - if (htutype) { + if (htu_type) { return true; } boolean success = false; - htuaddr = HTU21_ADDR; - htutype = htu21_readDeviceID(); - success = htu21_init(); - switch (htutype) { + htu_address = HTU21_ADDR; + htu_type = HtuReadDeviceId(); + success = HtuInit(); + switch (htu_type) { case HTU21_CHIPID: - strcpy_P(htustype, PSTR("HTU21")); - delayT=50; - delayH=16; + strcpy_P(htu_types, PSTR("HTU21")); + delay_temp=50; + delay_humidity=16; break; case SI7013_CHIPID: - strcpy_P(htustype, PSTR("SI7013")); - delayT=12; - delayH=23; + strcpy_P(htu_types, PSTR("SI7013")); + delay_temp=12; + delay_humidity=23; break; case SI7020_CHIPID: - strcpy_P(htustype, PSTR("SI7020")); - delayT=12; - delayH=23; + strcpy_P(htu_types, PSTR("SI7020")); + delay_temp=12; + delay_humidity=23; break; case SI7021_CHIPID: - strcpy_P(htustype, PSTR("SI7021")); - delayT=12; - delayH=23; + strcpy_P(htu_types, PSTR("SI7021")); + delay_temp=12; + delay_humidity=23; break; default: - strcpy_P(htustype, PSTR("T/RH?")); - delayT=50; - delayH=23; + strcpy_P(htu_types, PSTR("T/RH?")); + delay_temp=50; + delay_humidity=23; } if (success) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "%s " D_FOUND_AT " 0x%x"), htustype, htuaddr); - addLog(LOG_LEVEL_DEBUG); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "%s " D_FOUND_AT " 0x%x"), htu_types, htu_address); + AddLog(LOG_LEVEL_DEBUG); } else { - htutype = 0; + htu_type = 0; } return success; } @@ -255,43 +255,43 @@ uint8_t htu_detect() * Presentation \*********************************************************************************************/ -void htu_mqttPresent(uint8_t* djson) +void MqttShowHtu(uint8_t* djson) { - if (!htutype) { + if (!htu_type) { return; } char stemp1[10]; char stemp2[10]; - float t = htu21_readTemperature(); - float h = htu21_readHumidity(); - h = htu21_compensatedHumidity(h, t); - dtostrfd(t, sysCfg.flag.temperature_resolution, stemp1); - dtostrfd(h, sysCfg.flag.humidity_resolution, stemp2); - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, htustype, stemp1, stemp2); + float t = HtuReadTemperature(); + float h = HtuReadHumidity(); + h = HtuCompensatedHumidity(h, t); + dtostrfd(t, Settings.flag.temperature_resolution, stemp1); + dtostrfd(h, Settings.flag.humidity_resolution, stemp2); + snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, htu_types, stemp1, stemp2); *djson = 1; #ifdef USE_DOMOTICZ - domoticz_sensor2(stemp1, stemp2); + DomoticzTempHumSensor(stemp1, stemp2); #endif // USE_DOMOTICZ } #ifdef USE_WEBSERVER -String htu_webPresent() +String WebShowHtu() { String page = ""; - if (htutype) { + if (htu_type) { char stemp[10]; char sensor[80]; - float t_htu21 = htu21_readTemperature(); - float h_htu21 = htu21_readHumidity(); - h_htu21 = htu21_compensatedHumidity(h_htu21, t_htu21); - dtostrfi(t_htu21, sysCfg.flag.temperature_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, htustype, stemp, tempUnit()); + float t_htu21 = HtuReadTemperature(); + float h_htu21 = HtuReadHumidity(); + h_htu21 = HtuCompensatedHumidity(h_htu21, t_htu21); + dtostrfi(t_htu21, Settings.flag.temperature_resolution, stemp); + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, htu_types, stemp, TempUnit()); page += sensor; - dtostrfi(h_htu21, sysCfg.flag.humidity_resolution, stemp); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, htustype, stemp); + dtostrfi(h_htu21, Settings.flag.humidity_resolution, stemp); + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, htu_types, stemp); page += sensor; } return page; diff --git a/sonoff/xsns_sht1x.ino b/sonoff/xsns_sht1x.ino index c4e191791..676671244 100644 --- a/sonoff/xsns_sht1x.ino +++ b/sonoff/xsns_sht1x.ino @@ -34,9 +34,9 @@ enum { uint8_t sht_sda_pin; uint8_t sht_scl_pin; -uint8_t shttype = 0; +uint8_t sht_type = 0; -boolean sht_reset() +boolean ShtReset() { pinMode(sht_sda_pin, INPUT_PULLUP); pinMode(sht_scl_pin, OUTPUT); @@ -45,12 +45,12 @@ boolean sht_reset() digitalWrite(sht_scl_pin, HIGH); digitalWrite(sht_scl_pin, LOW); } - boolean success = sht_sendCommand(SHT1X_CMD_SOFT_RESET); + boolean success = ShtSendCommand(SHT1X_CMD_SOFT_RESET); delay(11); return success; } -boolean sht_sendCommand(const byte cmd) +boolean ShtSendCommand(const byte cmd) { pinMode(sht_sda_pin, OUTPUT); // Transmission Start sequence @@ -76,13 +76,13 @@ boolean sht_sendCommand(const byte cmd) ackerror = true; } if (ackerror) { - shttype = 0; - addLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_DID_NOT_ACK_COMMAND)); + sht_type = 0; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_DID_NOT_ACK_COMMAND)); } return (!ackerror); } -boolean sht_awaitResult() +boolean ShtAwaitResult() { // Maximum 320ms for 14 bit measurement for (byte i = 0; i < 16; i++) { @@ -91,12 +91,12 @@ boolean sht_awaitResult() } delay(20); } - addLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_BUSY)); - shttype = 0; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_BUSY)); + sht_type = 0; return false; } -int sht_readData() +int ShtReadData() { int val = 0; @@ -117,7 +117,7 @@ int sht_readData() return val; } -boolean sht_readTempHum(float &t, float &h) +boolean ShtReadTempHum(float &t, float &h) { float tempRaw; float humRaw; @@ -126,27 +126,27 @@ boolean sht_readTempHum(float &t, float &h) t = NAN; h = NAN; - if (!sht_reset()) { + if (!ShtReset()) { return false; } - if (!sht_sendCommand(SHT1X_CMD_MEASURE_TEMP)) { + if (!ShtSendCommand(SHT1X_CMD_MEASURE_TEMP)) { return false; } - if (!sht_awaitResult()) { + if (!ShtAwaitResult()) { return false; } - tempRaw = sht_readData(); + tempRaw = ShtReadData(); // Temperature conversion coefficients from SHT1X datasheet for version 4 const float d1 = -39.7; // 3.5V const float d2 = 0.01; // 14-bit t = d1 + (tempRaw * d2); - if (!sht_sendCommand(SHT1X_CMD_MEASURE_RH)) { + if (!ShtSendCommand(SHT1X_CMD_MEASURE_RH)) { return false; } - if (!sht_awaitResult()) { + if (!ShtAwaitResult()) { return false; } - humRaw = sht_readData(); + humRaw = ShtReadData(); // Temperature conversion coefficients from SHT1X datasheet for version 4 const float c1 = -2.0468; const float c2 = 0.0367; @@ -155,13 +155,13 @@ boolean sht_readTempHum(float &t, float &h) const float t2 = 0.00008; rhLinear = c1 + c2 * humRaw + c3 * humRaw * humRaw; h = (t - 25) * (t1 + t2 * humRaw) + rhLinear; - t = convertTemp(t); + t = ConvertTemp(t); return (!isnan(t) && !isnan(h)); } -boolean sht_detect() +boolean ShtDetect() { - if (shttype) { + if (sht_type) { return true; } @@ -170,59 +170,59 @@ boolean sht_detect() sht_sda_pin = pin[GPIO_I2C_SDA]; sht_scl_pin = pin[GPIO_I2C_SCL]; - if (sht_readTempHum(t, h)) { - shttype = 1; - addLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C D_SHT1X_FOUND)); + if (ShtReadTempHum(t, h)) { + sht_type = 1; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C D_SHT1X_FOUND)); } else { Wire.begin(sht_sda_pin, sht_scl_pin); - shttype = 0; + sht_type = 0; } - return shttype; + return sht_type; } /*********************************************************************************************\ * Presentation \*********************************************************************************************/ -void sht_mqttPresent(uint8_t* djson) +void MqttShowSht(uint8_t* djson) { - if (!shttype) { + if (!sht_type) { return; } float t; float h; - if (sht_readTempHum(t, h)) { + if (ShtReadTempHum(t, h)) { char stemp[10]; char shum[10]; - dtostrfd(t, sysCfg.flag.temperature_resolution, stemp); - dtostrfd(h, sysCfg.flag.humidity_resolution, shum); + dtostrfd(t, Settings.flag.temperature_resolution, stemp); + dtostrfd(h, Settings.flag.humidity_resolution, shum); snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, "SHT1X", stemp, shum); *djson = 1; #ifdef USE_DOMOTICZ - domoticz_sensor2(stemp, shum); + DomoticzTempHumSensor(stemp, shum); #endif // USE_DOMOTICZ } } #ifdef USE_WEBSERVER -String sht_webPresent() +String WebShowSht() { float t; float h; String page = ""; - if (shttype) { - if (sht_readTempHum(t, h)) { + if (sht_type) { + if (ShtReadTempHum(t, h)) { char stemp[10]; char shum[10]; char sensor[80]; - dtostrfi(t, sysCfg.flag.temperature_resolution, stemp); - dtostrfi(h, sysCfg.flag.humidity_resolution, shum); - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, "SHT1X", stemp, tempUnit()); + dtostrfi(t, Settings.flag.temperature_resolution, stemp); + dtostrfi(h, Settings.flag.humidity_resolution, shum); + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, "SHT1X", stemp, TempUnit()); page += sensor; snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, "SHT1X", shum); page += sensor; diff --git a/sonoff/xsns_veml6070.ino b/sonoff/xsns_veml6070.ino new file mode 100644 index 000000000..0a62a7737 --- /dev/null +++ b/sonoff/xsns_veml6070.ino @@ -0,0 +1,113 @@ +/* + xsns_veml6070.ino - VEML6070 ultra violet light sensor support for Sonoff-Tasmota + + Copyright (C) 2017 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 + 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 . +*/ + +#ifdef USE_I2C +#ifdef USE_VEML6070 +/*********************************************************************************************\ + * VEML6070 - Ultra Violet Light Intensity +\*********************************************************************************************/ + +#define VEML6070_ADDR_H 0x39 +#define VEML6070_ADDR_L 0x38 + +#define VEML6070_INTEGRATION_TIME 3 // 500msec integration time + +uint8_t veml6070_address; +uint8_t veml6070_type = 0; +char veml6070_types[9]; + +uint16_t Veml6070ReadUv() +{ + if (Wire.requestFrom(VEML6070_ADDR_H, 1) != 1) { + return -1; + } + uint16_t uvi = Wire.read(); + uvi <<= 8; + if (Wire.requestFrom(VEML6070_ADDR_L, 1) != 1) { + return -1; + } + uvi |= Wire.read(); + + return uvi; +} + +boolean Veml6070Detect() +{ + if (veml6070_type) { + return true; + } + + uint8_t status; + uint8_t itime = VEML6070_INTEGRATION_TIME; + boolean success = false; + + veml6070_address = VEML6070_ADDR_L; + Wire.beginTransmission(veml6070_address); + Wire.write((itime << 2) | 0x02); + status = Wire.endTransmission(); + if (!status) { + success = true; + veml6070_type = 1; + strcpy_P(veml6070_types, PSTR("VEML6070")); + } + if (success) { + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "%s " D_FOUND_AT " 0x%x"), veml6070_types, veml6070_address); + AddLog(LOG_LEVEL_DEBUG); + } else { + veml6070_type = 0; + } + return success; +} + +/*********************************************************************************************\ + * Presentation +\*********************************************************************************************/ + +void MqttShowVeml6070(uint8_t* djson) +{ + if (!veml6070_type) { + return; + } + + uint16_t uv = Veml6070ReadUv(); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_UV_LEVEL "\":%d}"), mqtt_data, veml6070_types, uv); + *djson = 1; +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_ILLUMINANCE, uv); +#endif // USE_DOMOTICZ +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_ULTRAVIOLET[] PROGMEM = + "VEML6070 " D_UV_LEVEL "%d"; + +String WebShowVeml6070() +{ + String page = ""; + if (veml6070_type) { + char sensor[80]; + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_ULTRAVIOLET, Veml6070ReadUv()); + page += sensor; + } + return page; +} +#endif // USE_WEBSERVER +#endif // USE_VEML6070 +#endif // USE_I2C +